@dxos/plugin-explorer 0.9.1-main.c7dcc2e112 → 0.10.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 (151) hide show
  1. package/dist/lib/neutral/ExplorerArticle-2WPXYTXV.mjs +101 -0
  2. package/dist/lib/neutral/ExplorerArticle-2WPXYTXV.mjs.map +7 -0
  3. package/dist/lib/neutral/ExplorerPlugin.mjs +1 -1
  4. package/dist/lib/neutral/NeighborhoodCompanion-WC6E3YE6.mjs +90 -0
  5. package/dist/lib/neutral/NeighborhoodCompanion-WC6E3YE6.mjs.map +7 -0
  6. package/dist/lib/neutral/app-graph-builder-L2TJ6GNR.mjs +37 -0
  7. package/dist/lib/neutral/app-graph-builder-L2TJ6GNR.mjs.map +7 -0
  8. package/dist/lib/neutral/capabilities/index.mjs +4 -2
  9. package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
  10. package/dist/lib/neutral/{chunk-JXYIG54N.mjs → chunk-4F6AT7RA.mjs} +4 -2
  11. package/dist/lib/neutral/chunk-4F6AT7RA.mjs.map +7 -0
  12. package/dist/lib/neutral/{chunk-7XUDLV6E.mjs → chunk-EZ52JY7X.mjs} +34 -31
  13. package/dist/lib/neutral/chunk-EZ52JY7X.mjs.map +7 -0
  14. package/dist/lib/neutral/{chunk-YBCHBVCJ.mjs → chunk-TTFPTHAQ.mjs} +8 -8
  15. package/dist/lib/neutral/chunk-TTFPTHAQ.mjs.map +7 -0
  16. package/dist/lib/neutral/components/index.mjs +430 -506
  17. package/dist/lib/neutral/components/index.mjs.map +4 -4
  18. package/dist/lib/neutral/containers/index.mjs +4 -2
  19. package/dist/lib/neutral/containers/index.mjs.map +3 -3
  20. package/dist/lib/neutral/{create-object-F6TKVAGV.mjs → create-object-WKIN3OB6.mjs} +3 -4
  21. package/dist/lib/neutral/{create-object-F6TKVAGV.mjs.map → create-object-WKIN3OB6.mjs.map} +3 -3
  22. package/dist/lib/neutral/hooks/index.mjs +64 -1
  23. package/dist/lib/neutral/hooks/index.mjs.map +4 -4
  24. package/dist/lib/neutral/index.mjs +1 -1
  25. package/dist/lib/neutral/meta.json +1 -1
  26. package/dist/lib/neutral/react-surface-EWPG5PUQ.mjs +39 -0
  27. package/dist/lib/neutral/react-surface-EWPG5PUQ.mjs.map +7 -0
  28. package/dist/lib/neutral/testing/index.mjs +2 -2
  29. package/dist/lib/neutral/testing/index.mjs.map +2 -2
  30. package/dist/lib/neutral/translations.mjs +4 -1
  31. package/dist/lib/neutral/translations.mjs.map +2 -2
  32. package/dist/lib/neutral/types/index.mjs +1 -1
  33. package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
  34. package/dist/types/src/capabilities/app-graph-builder.d.ts +9 -0
  35. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/create-object.d.ts +1 -7
  37. package/dist/types/src/capabilities/create-object.d.ts.map +1 -1
  38. package/dist/types/src/capabilities/index.d.ts +1 -0
  39. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  41. package/dist/types/src/components/Lattice/Lattice.d.ts +1 -1
  42. package/dist/types/src/components/Lattice/Lattice.d.ts.map +1 -1
  43. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +1 -1
  44. package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -1
  45. package/dist/types/src/components/Tree/Tree.stories.d.ts +1 -1
  46. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/Tree/index.d.ts +1 -3
  48. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  49. package/dist/types/src/components/Tree/types/tree.d.ts +10 -27
  50. package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
  51. package/dist/types/src/components/Tree/types/types.d.ts +1 -10
  52. package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
  53. package/dist/types/src/components/Visualization/Visualization.d.ts +39 -0
  54. package/dist/types/src/components/Visualization/Visualization.d.ts.map +1 -0
  55. package/dist/types/src/components/Visualization/Visualization.stories.d.ts +13 -0
  56. package/dist/types/src/components/Visualization/Visualization.stories.d.ts.map +1 -0
  57. package/dist/types/src/components/Visualization/index.d.ts +3 -0
  58. package/dist/types/src/components/Visualization/index.d.ts.map +1 -0
  59. package/dist/types/src/components/Visualization/variants.d.ts +53 -0
  60. package/dist/types/src/components/Visualization/variants.d.ts.map +1 -0
  61. package/dist/types/src/components/index.d.ts +1 -0
  62. package/dist/types/src/components/index.d.ts.map +1 -1
  63. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts +1 -1
  64. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -1
  65. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +2 -2
  66. package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -1
  67. package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts +14 -0
  68. package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts.map +1 -0
  69. package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts +2 -0
  70. package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts.map +1 -0
  71. package/dist/types/src/containers/index.d.ts +1 -0
  72. package/dist/types/src/containers/index.d.ts.map +1 -1
  73. package/dist/types/src/hooks/index.d.ts +1 -0
  74. package/dist/types/src/hooks/index.d.ts.map +1 -1
  75. package/dist/types/src/hooks/useNeighborhoodModel.d.ts +14 -0
  76. package/dist/types/src/hooks/useNeighborhoodModel.d.ts.map +1 -0
  77. package/dist/types/src/meta.d.ts +4 -0
  78. package/dist/types/src/meta.d.ts.map +1 -1
  79. package/dist/types/src/testing/relations.d.ts +1 -2
  80. package/dist/types/src/testing/relations.d.ts.map +1 -1
  81. package/dist/types/src/translations.d.ts +6 -0
  82. package/dist/types/src/translations.d.ts.map +1 -1
  83. package/dist/types/src/types/Graph.d.ts +6 -8
  84. package/dist/types/src/types/Graph.d.ts.map +1 -1
  85. package/dist/types/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +41 -37
  87. package/src/ExplorerPlugin.tsx +2 -1
  88. package/src/capabilities/app-graph-builder.ts +40 -0
  89. package/src/capabilities/create-object.ts +3 -2
  90. package/src/capabilities/index.ts +1 -0
  91. package/src/capabilities/react-surface.tsx +14 -4
  92. package/src/components/Lattice/Lattice.tsx +1 -2
  93. package/src/components/Tree/EdgeBundling.stories.tsx +5 -3
  94. package/src/components/Tree/Tree.stories.tsx +7 -2
  95. package/src/components/Tree/index.ts +3 -3
  96. package/src/components/Tree/types/tree.ts +6 -6
  97. package/src/components/Tree/types/types.ts +1 -11
  98. package/src/components/Visualization/Visualization.stories.tsx +104 -0
  99. package/src/components/Visualization/Visualization.tsx +209 -0
  100. package/src/components/Visualization/index.ts +6 -0
  101. package/src/components/Visualization/variants.ts +508 -0
  102. package/src/components/index.ts +1 -0
  103. package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +3 -3
  104. package/src/containers/ExplorerArticle/ExplorerArticle.tsx +7 -8
  105. package/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx +102 -0
  106. package/src/containers/NeighborhoodCompanion/index.ts +5 -0
  107. package/src/containers/index.ts +1 -0
  108. package/src/hooks/index.ts +1 -0
  109. package/src/hooks/useNeighborhoodModel.ts +81 -0
  110. package/src/testing/relations.ts +1 -3
  111. package/src/translations.ts +3 -0
  112. package/src/types/Graph.ts +18 -20
  113. package/dist/lib/neutral/ExplorerArticle-MHEINWUL.mjs +0 -460
  114. package/dist/lib/neutral/ExplorerArticle-MHEINWUL.mjs.map +0 -7
  115. package/dist/lib/neutral/chunk-7XUDLV6E.mjs.map +0 -7
  116. package/dist/lib/neutral/chunk-IKHJV3Q4.mjs +0 -20
  117. package/dist/lib/neutral/chunk-IKHJV3Q4.mjs.map +0 -7
  118. package/dist/lib/neutral/chunk-JXYIG54N.mjs.map +0 -7
  119. package/dist/lib/neutral/chunk-YBCHBVCJ.mjs.map +0 -7
  120. package/dist/lib/neutral/react-surface-APBW2VQG.mjs +0 -26
  121. package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +0 -7
  122. package/dist/types/src/components/Tree/Tree.d.ts +0 -24
  123. package/dist/types/src/components/Tree/Tree.d.ts.map +0 -1
  124. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +0 -40
  125. package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +0 -1
  126. package/dist/types/src/components/Tree/layout/RadialTree.d.ts +0 -37
  127. package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +0 -1
  128. package/dist/types/src/components/Tree/layout/TidyTree.d.ts +0 -26
  129. package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +0 -1
  130. package/dist/types/src/components/Tree/layout/hierarchy.d.ts +0 -17
  131. package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +0 -1
  132. package/dist/types/src/components/Tree/layout/index.d.ts +0 -6
  133. package/dist/types/src/components/Tree/layout/index.d.ts.map +0 -1
  134. package/dist/types/src/components/Tree/layout/slots.d.ts +0 -7
  135. package/dist/types/src/components/Tree/layout/slots.d.ts.map +0 -1
  136. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +0 -15
  137. package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +0 -1
  138. package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts +0 -18
  139. package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts.map +0 -1
  140. package/dist/types/src/containers/ExplorerArticle/variants.d.ts +0 -9
  141. package/dist/types/src/containers/ExplorerArticle/variants.d.ts.map +0 -1
  142. package/src/components/Tree/Tree.tsx +0 -81
  143. package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +0 -335
  144. package/src/components/Tree/layout/RadialTree.tsx +0 -242
  145. package/src/components/Tree/layout/TidyTree.tsx +0 -246
  146. package/src/components/Tree/layout/hierarchy.ts +0 -32
  147. package/src/components/Tree/layout/index.ts +0 -9
  148. package/src/components/Tree/layout/slots.ts +0 -19
  149. package/src/components/Tree/layout/useContainerSize.ts +0 -43
  150. package/src/containers/ExplorerArticle/Visualization.tsx +0 -523
  151. package/src/containers/ExplorerArticle/variants.ts +0 -47
@@ -0,0 +1,101 @@
1
+ import "./chunk-J5LGTIGS.mjs";
2
+
3
+ // src/containers/ExplorerArticle/ExplorerArticle.tsx
4
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
5
+ import { AppSurface } from "@dxos/app-toolkit/ui";
6
+ import { Obj } from "@dxos/echo";
7
+ import { QueryBuilder } from "@dxos/echo-query";
8
+ import { useObject } from "@dxos/react-client/echo";
9
+ import { DxAnchorActivate, Icon, Panel, Toolbar } from "@dxos/react-ui";
10
+ import { QueryEditor } from "@dxos/react-ui-components";
11
+ import "@dxos/react-ui-graph/styles/graph.css";
12
+ import { VARIANTS, Visualization, isVariant } from "#components";
13
+ import { useGraphModel } from "#hooks";
14
+ var ExplorerArticle = ({ role, subject, variant }) => {
15
+ const [view] = useObject(subject);
16
+ const [filter, setFilter] = useState();
17
+ const db = view && Obj.getDatabase(view);
18
+ const model = useGraphModel(db, filter);
19
+ const builder = useMemo(() => new QueryBuilder(), []);
20
+ const handleChange = useCallback((value) => {
21
+ setFilter(builder.build(value).filter);
22
+ }, [
23
+ builder
24
+ ]);
25
+ const [selected, setSelected] = useState(isVariant(variant) ? variant : "force");
26
+ useEffect(() => {
27
+ if (isVariant(variant)) {
28
+ setSelected(variant);
29
+ }
30
+ }, [
31
+ variant
32
+ ]);
33
+ const handleVariantChange = useCallback((value) => {
34
+ if (isVariant(value)) {
35
+ setSelected(value);
36
+ }
37
+ }, []);
38
+ const handleDismiss = useCallback(() => {
39
+ document.defaultView?.dispatchEvent(new DxAnchorActivate({
40
+ dxn: "",
41
+ label: "",
42
+ trigger: document.body,
43
+ state: false
44
+ }));
45
+ }, []);
46
+ const handleHover = useCallback((node, event) => {
47
+ if (!node || !event) {
48
+ return;
49
+ }
50
+ const obj = node.data;
51
+ if (!obj || !Obj.isObject(obj)) {
52
+ return;
53
+ }
54
+ const dxn = Obj.getURI(obj);
55
+ if (!dxn) {
56
+ return;
57
+ }
58
+ const target = event.target;
59
+ target.dispatchEvent(new DxAnchorActivate({
60
+ dxn,
61
+ kind: "card",
62
+ trigger: target,
63
+ label: Obj.getLabel(obj) ?? dxn
64
+ }));
65
+ }, []);
66
+ const showToolbar = role === AppSurface.Article.role;
67
+ if (!db || !model) {
68
+ return null;
69
+ }
70
+ return /* @__PURE__ */ React.createElement(Panel.Root, {
71
+ role
72
+ }, showToolbar && /* @__PURE__ */ React.createElement(Panel.Toolbar, {
73
+ asChild: true
74
+ }, /* @__PURE__ */ React.createElement(Toolbar.Root, null, /* @__PURE__ */ React.createElement(QueryEditor, {
75
+ db,
76
+ onChange: handleChange
77
+ }), /* @__PURE__ */ React.createElement(Toolbar.ToggleGroup, {
78
+ type: "single",
79
+ value: selected,
80
+ onValueChange: handleVariantChange
81
+ }, VARIANTS.map(({ value, icon, label }) => /* @__PURE__ */ React.createElement(Toolbar.ToggleGroupItem, {
82
+ key: value,
83
+ value,
84
+ "aria-label": label,
85
+ title: label
86
+ }, /* @__PURE__ */ React.createElement(Icon, {
87
+ icon,
88
+ size: 4
89
+ })))))), /* @__PURE__ */ React.createElement(Panel.Content, null, /* @__PURE__ */ React.createElement(Visualization.Root, {
90
+ classNames: "bg-base-surface",
91
+ variant: selected,
92
+ model,
93
+ onSurfaceClick: handleDismiss
94
+ }, /* @__PURE__ */ React.createElement(Visualization.Graph, {
95
+ onNodeHover: handleHover
96
+ }))));
97
+ };
98
+ export {
99
+ ExplorerArticle as default
100
+ };
101
+ //# sourceMappingURL=ExplorerArticle-2WPXYTXV.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/ExplorerArticle/ExplorerArticle.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { AppSurface } from '@dxos/app-toolkit/ui';\nimport { type Filter, Obj, type View } from '@dxos/echo';\nimport { QueryBuilder } from '@dxos/echo-query';\nimport { useObject } from '@dxos/react-client/echo';\nimport { DxAnchorActivate, Icon, Panel, Toolbar } from '@dxos/react-ui';\nimport { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';\nimport { type TreeNode } from '@dxos/react-ui-graph';\nimport '@dxos/react-ui-graph/styles/graph.css';\n\nimport { type ExplorerArticleVariant, VARIANTS, Visualization, isVariant } from '#components';\nimport { useGraphModel } from '#hooks';\n\nexport type { ExplorerArticleVariant } from '#components';\n\nexport type ExplorerArticleProps = AppSurface.ObjectArticleProps<View.View>;\n\nexport const ExplorerArticle = ({ role, subject, variant }: ExplorerArticleProps) => {\n const [view] = useObject(subject);\n const [filter, setFilter] = useState<Filter.Any>();\n\n const db = view && Obj.getDatabase(view);\n const model = useGraphModel(db, filter);\n\n const builder = useMemo(() => new QueryBuilder(), []);\n const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>(\n (value) => {\n setFilter(builder.build(value).filter);\n },\n [builder],\n );\n\n const [selected, setSelected] = useState<ExplorerArticleVariant>(isVariant(variant) ? variant : 'force');\n useEffect(() => {\n if (isVariant(variant)) {\n setSelected(variant);\n }\n }, [variant]);\n\n const handleVariantChange = useCallback((value: string) => {\n if (isVariant(value)) {\n setSelected(value);\n }\n }, []);\n\n // Dismiss the preview popover. The dxn/label/trigger fields are placeholders ignored on\n // `state: false`.\n const handleDismiss = useCallback(() => {\n document.defaultView?.dispatchEvent(\n new DxAnchorActivate({ dxn: '', label: '', trigger: document.body, state: false }),\n );\n }, []);\n\n const handleHover = useCallback((node: TreeNode | null, event?: MouseEvent) => {\n // Pointer left the node/label: keep the popover open so it can be hovered/interacted with.\n // The popover is dismissed only on an explicit click on the component surface (handleDismiss).\n if (!node || !event) {\n return;\n }\n const obj = node.data;\n if (!obj || !Obj.isObject(obj)) {\n return;\n }\n const dxn = Obj.getURI(obj);\n if (!dxn) {\n return;\n }\n\n const target = event.target as HTMLElement;\n target.dispatchEvent(\n new DxAnchorActivate({\n dxn,\n kind: 'card',\n trigger: target,\n label: Obj.getLabel(obj) ?? dxn,\n }),\n );\n }, []);\n\n const showToolbar = role === AppSurface.Article.role;\n\n if (!db || !model) {\n return null;\n }\n\n return (\n <Panel.Root role={role}>\n {showToolbar && (\n <Panel.Toolbar asChild>\n <Toolbar.Root>\n <QueryEditor db={db} onChange={handleChange} />\n <Toolbar.ToggleGroup type='single' value={selected} onValueChange={handleVariantChange}>\n {VARIANTS.map(({ value, icon, label }) => (\n <Toolbar.ToggleGroupItem key={value} value={value} aria-label={label} title={label}>\n <Icon icon={icon} size={4} />\n </Toolbar.ToggleGroupItem>\n ))}\n </Toolbar.ToggleGroup>\n </Toolbar.Root>\n </Panel.Toolbar>\n )}\n <Panel.Content>\n <Visualization.Root\n classNames='bg-base-surface'\n variant={selected}\n model={model}\n onSurfaceClick={handleDismiss}\n >\n <Visualization.Graph onNodeHover={handleHover} />\n </Visualization.Root>\n </Panel.Content>\n </Panel.Root>\n );\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "useCallback", "useEffect", "useMemo", "useState", "AppSurface", "Obj", "QueryBuilder", "useObject", "DxAnchorActivate", "Icon", "Panel", "Toolbar", "QueryEditor", "VARIANTS", "Visualization", "isVariant", "useGraphModel", "ExplorerArticle", "role", "subject", "variant", "view", "filter", "setFilter", "db", "getDatabase", "model", "builder", "handleChange", "value", "build", "selected", "setSelected", "handleVariantChange", "handleDismiss", "document", "defaultView", "dispatchEvent", "dxn", "label", "trigger", "body", "state", "handleHover", "node", "event", "obj", "data", "isObject", "getURI", "target", "kind", "getLabel", "showToolbar", "Article", "Root", "asChild", "onChange", "ToggleGroup", "type", "onValueChange", "map", "icon", "ToggleGroupItem", "key", "aria-label", "title", "size", "Content", "classNames", "onSurfaceClick", "Graph", "onNodeHover"]
7
+ }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ExplorerPlugin,
3
3
  ExplorerPlugin_default
4
- } from "./chunk-JXYIG54N.mjs";
4
+ } from "./chunk-4F6AT7RA.mjs";
5
5
  import "./chunk-J5LGTIGS.mjs";
6
6
  export {
7
7
  ExplorerPlugin,
@@ -0,0 +1,90 @@
1
+ import "./chunk-J5LGTIGS.mjs";
2
+
3
+ // src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx
4
+ import React, { useCallback, useState } from "react";
5
+ import { Obj } from "@dxos/echo";
6
+ import { DxAnchorActivate, Panel, Toolbar, useTranslation } from "@dxos/react-ui";
7
+ import "@dxos/react-ui-graph/styles/graph.css";
8
+ import { Visualization } from "#components";
9
+ import { DEFAULT_NEIGHBORHOOD_DEPTH, useNeighborhoodModel } from "#hooks";
10
+ import { meta } from "#meta";
11
+ var DEPTHS = [
12
+ 1,
13
+ 2,
14
+ 3
15
+ ];
16
+ var NeighborhoodCompanion = ({ role = "article", subject }) => {
17
+ const { t } = useTranslation(meta.profile.key);
18
+ const [depth, setDepth] = useState(DEFAULT_NEIGHBORHOOD_DEPTH);
19
+ const model = useNeighborhoodModel(subject, depth);
20
+ const handleDepthChange = useCallback((value) => {
21
+ const next = Number.parseInt(value, 10);
22
+ if (Number.isFinite(next)) {
23
+ setDepth(next);
24
+ }
25
+ }, []);
26
+ const handleDismiss = useCallback(() => {
27
+ document.defaultView?.dispatchEvent(new DxAnchorActivate({
28
+ dxn: "",
29
+ label: "",
30
+ trigger: document.body,
31
+ state: false
32
+ }));
33
+ }, []);
34
+ const handleHover = useCallback((node, event) => {
35
+ if (!node || !event) {
36
+ return;
37
+ }
38
+ const obj = node.data;
39
+ if (!obj || !Obj.isObject(obj)) {
40
+ return;
41
+ }
42
+ const dxn = Obj.getURI(obj);
43
+ if (!dxn) {
44
+ return;
45
+ }
46
+ const target = event.target;
47
+ target.dispatchEvent(new DxAnchorActivate({
48
+ dxn,
49
+ kind: "card",
50
+ trigger: target,
51
+ label: Obj.getLabel(obj) ?? dxn
52
+ }));
53
+ }, []);
54
+ if (!subject || !model) {
55
+ return null;
56
+ }
57
+ return /* @__PURE__ */ React.createElement(Panel.Root, {
58
+ role
59
+ }, /* @__PURE__ */ React.createElement(Panel.Toolbar, {
60
+ asChild: true
61
+ }, /* @__PURE__ */ React.createElement(Toolbar.Root, null, /* @__PURE__ */ React.createElement("div", {
62
+ role: "none",
63
+ className: "grow"
64
+ }), /* @__PURE__ */ React.createElement(Toolbar.ToggleGroup, {
65
+ type: "single",
66
+ value: String(depth),
67
+ onValueChange: handleDepthChange
68
+ }, DEPTHS.map((value) => /* @__PURE__ */ React.createElement(Toolbar.ToggleGroupItem, {
69
+ key: value,
70
+ value: String(value),
71
+ "aria-label": t("depth.label", {
72
+ count: value
73
+ }),
74
+ title: t("depth.label", {
75
+ count: value
76
+ })
77
+ }, value))))), /* @__PURE__ */ React.createElement(Panel.Content, null, /* @__PURE__ */ React.createElement(Visualization.Root, {
78
+ classNames: "bg-base-surface",
79
+ model,
80
+ variant: "neighborhood",
81
+ focus: subject.id,
82
+ onSurfaceClick: handleDismiss
83
+ }, /* @__PURE__ */ React.createElement(Visualization.Graph, {
84
+ onNodeHover: handleHover
85
+ }))));
86
+ };
87
+ export {
88
+ NeighborhoodCompanion as default
89
+ };
90
+ //# sourceMappingURL=NeighborhoodCompanion-WC6E3YE6.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport { DxAnchorActivate, Panel, Toolbar, useTranslation } from '@dxos/react-ui';\nimport { type TreeNode } from '@dxos/react-ui-graph';\nimport '@dxos/react-ui-graph/styles/graph.css';\n\nimport { Visualization } from '#components';\nimport { DEFAULT_NEIGHBORHOOD_DEPTH, useNeighborhoodModel } from '#hooks';\nimport { meta } from '#meta';\n\n/** Selectable traversal depths offered in the companion toolbar. */\nconst DEPTHS = [1, 2, 3] as const;\n\nexport type NeighborhoodCompanionProps = {\n role?: string;\n /** The active node whose neighbourhood is rendered (passed as the companion subject). */\n subject: Obj.Any;\n};\n\n/**\n * Companion that renders the n-hop neighbourhood of the active node as an ego-centric radial graph,\n * with the active node at the centre. Depth (number of hops traversed) is adjustable in the toolbar.\n */\nexport const NeighborhoodCompanion = ({ role = 'article', subject }: NeighborhoodCompanionProps) => {\n const { t } = useTranslation(meta.profile.key);\n const [depth, setDepth] = useState<number>(DEFAULT_NEIGHBORHOOD_DEPTH);\n const model = useNeighborhoodModel(subject, depth);\n\n const handleDepthChange = useCallback((value: string) => {\n const next = Number.parseInt(value, 10);\n if (Number.isFinite(next)) {\n setDepth(next);\n }\n }, []);\n\n // Dismiss the preview popover. The dxn/label/trigger fields are placeholders ignored on `state: false`.\n const handleDismiss = useCallback(() => {\n document.defaultView?.dispatchEvent(\n new DxAnchorActivate({ dxn: '', label: '', trigger: document.body, state: false }),\n );\n }, []);\n\n const handleHover = useCallback((node: TreeNode | null, event?: MouseEvent) => {\n // Pointer left the node/label: keep the popover open so it can be hovered/interacted with.\n if (!node || !event) {\n return;\n }\n const obj = node.data;\n if (!obj || !Obj.isObject(obj)) {\n return;\n }\n const dxn = Obj.getURI(obj);\n if (!dxn) {\n return;\n }\n\n const target = event.target as HTMLElement;\n target.dispatchEvent(new DxAnchorActivate({ dxn, kind: 'card', trigger: target, label: Obj.getLabel(obj) ?? dxn }));\n }, []);\n\n if (!subject || !model) {\n return null;\n }\n\n return (\n <Panel.Root role={role}>\n <Panel.Toolbar asChild>\n <Toolbar.Root>\n <div role='none' className='grow' />\n <Toolbar.ToggleGroup type='single' value={String(depth)} onValueChange={handleDepthChange}>\n {DEPTHS.map((value) => (\n <Toolbar.ToggleGroupItem\n key={value}\n value={String(value)}\n aria-label={t('depth.label', { count: value })}\n title={t('depth.label', { count: value })}\n >\n {value}\n </Toolbar.ToggleGroupItem>\n ))}\n </Toolbar.ToggleGroup>\n </Toolbar.Root>\n </Panel.Toolbar>\n <Panel.Content>\n <Visualization.Root\n classNames='bg-base-surface'\n model={model}\n variant='neighborhood'\n focus={subject.id}\n onSurfaceClick={handleDismiss}\n >\n <Visualization.Graph onNodeHover={handleHover} />\n </Visualization.Root>\n </Panel.Content>\n </Panel.Root>\n );\n};\n"],
5
+ "mappings": ";;;AAIA,OAAOA,SAASC,aAAaC,gBAAgB;AAE7C,SAASC,WAAW;AACpB,SAASC,kBAAkBC,OAAOC,SAASC,sBAAsB;AAEjE,OAAO;AAEP,SAASC,qBAAqB;AAC9B,SAASC,4BAA4BC,4BAA4B;AACjE,SAASC,YAAY;AAGrB,IAAMC,SAAS;EAAC;EAAG;EAAG;;AAYf,IAAMC,wBAAwB,CAAC,EAAEC,OAAO,WAAWC,QAAO,MAA8B;AAC7F,QAAM,EAAEC,EAAC,IAAKT,eAAeI,KAAKM,QAAQC,GAAG;AAC7C,QAAM,CAACC,OAAOC,QAAAA,IAAYlB,SAAiBO,0BAAAA;AAC3C,QAAMY,QAAQX,qBAAqBK,SAASI,KAAAA;AAE5C,QAAMG,oBAAoBrB,YAAY,CAACsB,UAAAA;AACrC,UAAMC,OAAOC,OAAOC,SAASH,OAAO,EAAA;AACpC,QAAIE,OAAOE,SAASH,IAAAA,GAAO;AACzBJ,eAASI,IAAAA;IACX;EACF,GAAG,CAAA,CAAE;AAGL,QAAMI,gBAAgB3B,YAAY,MAAA;AAChC4B,aAASC,aAAaC,cACpB,IAAI3B,iBAAiB;MAAE4B,KAAK;MAAIC,OAAO;MAAIC,SAASL,SAASM;MAAMC,OAAO;IAAM,CAAA,CAAA;EAEpF,GAAG,CAAA,CAAE;AAEL,QAAMC,cAAcpC,YAAY,CAACqC,MAAuBC,UAAAA;AAEtD,QAAI,CAACD,QAAQ,CAACC,OAAO;AACnB;IACF;AACA,UAAMC,MAAMF,KAAKG;AACjB,QAAI,CAACD,OAAO,CAACrC,IAAIuC,SAASF,GAAAA,GAAM;AAC9B;IACF;AACA,UAAMR,MAAM7B,IAAIwC,OAAOH,GAAAA;AACvB,QAAI,CAACR,KAAK;AACR;IACF;AAEA,UAAMY,SAASL,MAAMK;AACrBA,WAAOb,cAAc,IAAI3B,iBAAiB;MAAE4B;MAAKa,MAAM;MAAQX,SAASU;MAAQX,OAAO9B,IAAI2C,SAASN,GAAAA,KAAQR;IAAI,CAAA,CAAA;EAClH,GAAG,CAAA,CAAE;AAEL,MAAI,CAACjB,WAAW,CAACM,OAAO;AACtB,WAAO;EACT;AAEA,SACE,sBAAA,cAAChB,MAAM0C,MAAI;IAACjC;KACV,sBAAA,cAACT,MAAMC,SAAO;IAAC0C,SAAAA;KACb,sBAAA,cAAC1C,QAAQyC,MAAI,MACX,sBAAA,cAACE,OAAAA;IAAInC,MAAK;IAAOoC,WAAU;MAC3B,sBAAA,cAAC5C,QAAQ6C,aAAW;IAACC,MAAK;IAAS7B,OAAO8B,OAAOlC,KAAAA;IAAQmC,eAAehC;KACrEV,OAAO2C,IAAI,CAAChC,UACX,sBAAA,cAACjB,QAAQkD,iBAAe;IACtBtC,KAAKK;IACLA,OAAO8B,OAAO9B,KAAAA;IACdkC,cAAYzC,EAAE,eAAe;MAAE0C,OAAOnC;IAAM,CAAA;IAC5CoC,OAAO3C,EAAE,eAAe;MAAE0C,OAAOnC;IAAM,CAAA;KAEtCA,KAAAA,CAAAA,CAAAA,CAAAA,CAAAA,GAMX,sBAAA,cAAClB,MAAMuD,SAAO,MACZ,sBAAA,cAACpD,cAAcuC,MAAI;IACjBc,YAAW;IACXxC;IACAyC,SAAQ;IACRC,OAAOhD,QAAQiD;IACfC,gBAAgBrC;KAEhB,sBAAA,cAACpB,cAAc0D,OAAK;IAACC,aAAa9B;;AAK5C;",
6
+ "names": ["React", "useCallback", "useState", "Obj", "DxAnchorActivate", "Panel", "Toolbar", "useTranslation", "Visualization", "DEFAULT_NEIGHBORHOOD_DEPTH", "useNeighborhoodModel", "meta", "DEPTHS", "NeighborhoodCompanion", "role", "subject", "t", "profile", "key", "depth", "setDepth", "model", "handleDepthChange", "value", "next", "Number", "parseInt", "isFinite", "handleDismiss", "document", "defaultView", "dispatchEvent", "dxn", "label", "trigger", "body", "state", "handleHover", "node", "event", "obj", "data", "isObject", "getURI", "target", "kind", "getLabel", "Root", "asChild", "div", "className", "ToggleGroup", "type", "String", "onValueChange", "map", "ToggleGroupItem", "aria-label", "count", "title", "Content", "classNames", "variant", "focus", "id", "onSurfaceClick", "Graph", "onNodeHover"]
7
+ }
@@ -0,0 +1,37 @@
1
+ import "./chunk-J5LGTIGS.mjs";
2
+
3
+ // src/capabilities/app-graph-builder.ts
4
+ import * as Effect from "effect/Effect";
5
+ import { Capability } from "@dxos/app-framework";
6
+ import { AppCapabilities, AppNode } from "@dxos/app-toolkit";
7
+ import { GraphBuilder, NodeMatcher } from "@dxos/plugin-graph";
8
+ import { linkedSegment } from "@dxos/react-ui-attention";
9
+ import { Position } from "@dxos/util";
10
+ import { meta } from "#meta";
11
+ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
12
+ const extensions = yield* Effect.all([
13
+ GraphBuilder.createExtension({
14
+ id: "neighborhoodCompanion",
15
+ match: NodeMatcher.whenEchoObjectMatches,
16
+ connector: () => Effect.succeed([
17
+ AppNode.makeCompanion({
18
+ id: linkedSegment("neighborhood"),
19
+ label: [
20
+ "neighborhood-companion.label",
21
+ {
22
+ ns: meta.profile.key
23
+ }
24
+ ],
25
+ icon: "ph--share-network--regular",
26
+ data: "neighborhood",
27
+ position: Position.last
28
+ })
29
+ ])
30
+ })
31
+ ]);
32
+ return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
33
+ }));
34
+ export {
35
+ app_graph_builder_default as default
36
+ };
37
+ //# sourceMappingURL=app-graph-builder-L2TJ6GNR.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/capabilities/app-graph-builder.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { AppCapabilities, AppNode } from '@dxos/app-toolkit';\nimport { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';\nimport { linkedSegment } from '@dxos/react-ui-attention';\nimport { Position } from '@dxos/util';\n\nimport { meta } from '#meta';\n\n/**\n * Offers a \"Neighborhood\" companion on any ECHO object. The matched node is passed through as the\n * companion's `companionTo` (the active node), which the surface renders as an ego-centric graph.\n */\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const extensions = yield* Effect.all([\n GraphBuilder.createExtension({\n id: 'neighborhoodCompanion',\n match: NodeMatcher.whenEchoObjectMatches,\n connector: () =>\n Effect.succeed([\n AppNode.makeCompanion({\n id: linkedSegment('neighborhood'),\n label: ['neighborhood-companion.label', { ns: meta.profile.key }],\n icon: 'ph--share-network--regular',\n data: 'neighborhood',\n position: Position.last,\n }),\n ]),\n }),\n ]);\n\n return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],
5
+ "mappings": ";;;AAIA,YAAYA,YAAY;AAExB,SAASC,kBAAkB;AAC3B,SAASC,iBAAiBC,eAAe;AACzC,SAASC,cAAcC,mBAAmB;AAC1C,SAASC,qBAAqB;AAC9B,SAASC,gBAAgB;AAEzB,SAASC,YAAY;AAMrB,IAAA,4BAAeP,WAAWQ,WACjBC,kBAAW,aAAA;AAChB,QAAMC,aAAa,OAAcC,WAAI;IACnCR,aAAaS,gBAAgB;MAC3BC,IAAI;MACJC,OAAOV,YAAYW;MACnBC,WAAW,MACFC,eAAQ;QACbf,QAAQgB,cAAc;UACpBL,IAAIR,cAAc,cAAA;UAClBc,OAAO;YAAC;YAAgC;cAAEC,IAAIb,KAAKc,QAAQC;YAAI;;UAC/DC,MAAM;UACNC,MAAM;UACNC,UAAUnB,SAASoB;QACrB,CAAA;OACD;IACL,CAAA;GACD;AAED,SAAO1B,WAAW2B,YAAY1B,gBAAgB2B,iBAAiBlB,UAAAA;AACjE,CAAA,CAAA;",
6
+ "names": ["Effect", "Capability", "AppCapabilities", "AppNode", "GraphBuilder", "NodeMatcher", "linkedSegment", "Position", "meta", "makeModule", "fnUntraced", "extensions", "all", "createExtension", "id", "match", "whenEchoObjectMatches", "connector", "succeed", "makeCompanion", "label", "ns", "profile", "key", "icon", "data", "position", "last", "contributes", "AppGraphBuilder"]
7
+ }
@@ -2,9 +2,11 @@ import "../chunk-J5LGTIGS.mjs";
2
2
 
3
3
  // src/capabilities/index.ts
4
4
  import { Capability } from "@dxos/app-framework";
5
- var CreateObject = Capability.lazy("CreateObject", () => import("../create-object-F6TKVAGV.mjs"));
6
- var ReactSurface = Capability.lazy("ReactSurface", () => import("../react-surface-APBW2VQG.mjs"));
5
+ var AppGraphBuilder = Capability.lazy("AppGraphBuilder", () => import("../app-graph-builder-L2TJ6GNR.mjs"));
6
+ var CreateObject = Capability.lazy("CreateObject", () => import("../create-object-WKIN3OB6.mjs"));
7
+ var ReactSurface = Capability.lazy("ReactSurface", () => import("../react-surface-EWPG5PUQ.mjs"));
7
8
  export {
9
+ AppGraphBuilder,
8
10
  CreateObject,
9
11
  ReactSurface
10
12
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/capabilities/index.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\n\nexport const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));\nexport const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));\n"],
5
- "mappings": ";;;AAIA,SAASA,kBAAkB;AAEpB,IAAMC,eAAeD,WAAWE,KAAK,gBAAgB,MAAM,OAAO,+BAAA,CAAA;AAClE,IAAMC,eAAeH,WAAWE,KAAK,gBAAgB,MAAM,OAAO,+BAAA,CAAA;",
6
- "names": ["Capability", "CreateObject", "lazy", "ReactSurface"]
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\n\nexport const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));\nexport const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));\nexport const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));\n"],
5
+ "mappings": ";;;AAIA,SAASA,kBAAkB;AAEpB,IAAMC,kBAAkBD,WAAWE,KAAK,mBAAmB,MAAM,OAAO,mCAAA,CAAA;AACxE,IAAMC,eAAeH,WAAWE,KAAK,gBAAgB,MAAM,OAAO,+BAAA,CAAA;AAClE,IAAME,eAAeJ,WAAWE,KAAK,gBAAgB,MAAM,OAAO,+BAAA,CAAA;",
6
+ "names": ["Capability", "AppGraphBuilder", "lazy", "CreateObject", "ReactSurface"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  // src/ExplorerPlugin.tsx
2
2
  import { Plugin } from "@dxos/app-framework";
3
3
  import { AppPlugin } from "@dxos/app-toolkit";
4
- import { CreateObject, ReactSurface } from "#capabilities";
4
+ import { AppGraphBuilder, CreateObject, ReactSurface } from "#capabilities";
5
5
  import { meta } from "#meta";
6
6
  import { translations } from "#translations";
7
7
  import { Graph } from "#types";
@@ -12,6 +12,8 @@ var PLUGIN_default = "---\nid: org.dxos.plugin.explorer\nname: ExplorerPlugin\nv
12
12
  // src/ExplorerPlugin.tsx
13
13
  var ExplorerPlugin = Plugin.define(meta).pipe(AppPlugin.addCreateObjectModule({
14
14
  activate: CreateObject
15
+ }), AppPlugin.addAppGraphModule({
16
+ activate: AppGraphBuilder
15
17
  }), AppPlugin.addSchemaModule({
16
18
  schema: [
17
19
  Graph.Graph
@@ -34,4 +36,4 @@ export {
34
36
  ExplorerPlugin,
35
37
  ExplorerPlugin_default
36
38
  };
37
- //# sourceMappingURL=chunk-JXYIG54N.mjs.map
39
+ //# sourceMappingURL=chunk-4F6AT7RA.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/ExplorerPlugin.tsx", "raw-loader:/__w/dxos/dxos/packages/plugins/plugin-explorer/PLUGIN.mdl"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\n\nimport { AppGraphBuilder, CreateObject, ReactSurface } from '#capabilities';\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { Graph } from '#types';\n\n// eslint-disable-next-line import/no-relative-packages\nimport pluginSpec from '../PLUGIN.mdl?raw';\n\nexport const ExplorerPlugin = Plugin.define(meta).pipe(\n AppPlugin.addCreateObjectModule({ activate: CreateObject }),\n AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),\n AppPlugin.addSchemaModule({ schema: [Graph.Graph] }),\n AppPlugin.addSurfaceModule({ activate: ReactSurface }),\n AppPlugin.addTranslationsModule({ translations }),\n AppPlugin.addPluginAssetModule({\n asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },\n }),\n Plugin.make,\n);\n\nexport default ExplorerPlugin;\n", "---\nid: org.dxos.plugin.explorer\nname: ExplorerPlugin\nversion: 0.1.0\n---\n\nAn interactive hypergraph visualization plugin for `DXOS` Composer that reveals relationships between objects in a workspace.\nThe plugin renders a live `Graph` object \u2014 backed by a `View` and a `QueryAST` query \u2014 through four switchable layout\nvariants: force-directed, radial cluster, edge bundling, and lattice.\nNode colours are derived from ECHO object types; hovering a node triggers an anchor-card preview.\n\n## Extensions\n\nThe following extension dialects are used in this document.\nEach extension is defined in the Appendix or resolved via its URI.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `test` | `org.dxos.mdl.test@1.0` |\n| `component` | `org.dxos.mdl.component@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n\n## Types\n\n```mdl\ntype QueryInput\n fields:\n raw?: string # raw query string entered by the user\n ast: QueryAST.Query # compiled AST produced by QueryBuilder\n```\n\n```mdl\ntype GraphObject\n desc: ECHO-persistent object that describes a hypergraph visualisation session.\n fields:\n name?: string\n view: Ref<View> # schema view that defines visible fields\n query: QueryInput\n```\n\n```mdl\ntype ExplorerVariant\n literals: force | cluster | bundle | lattice\n```\n\n## Components\n\n```mdl\ncomponent ExplorerArticle\n desc: |\n Top-level article / section surface for a Graph object.\n Renders one of four SVG layout variants and a toolbar for switching between them.\n props:\n role: article | section\n subject: Ref<View>\n attendableId?: string\n state:\n variant: ExplorerVariant # active layout; default force\n filter?: Filter.Any # compiled from toolbar query input\n model?: SpaceGraphModel # live reactive graph built from db + filter\n slots:\n toolbar?: ReactNode # shown only when role === article\n actions:\n setVariant(v: ExplorerVariant)\n setFilter(raw: string)\n layout: |\n \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 [toolbar slot \u2014 article only] \u2502\n \u2502 [QueryEditor] [variant tabs] \u2502\n \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n \u2502 \u2502\n \u2502 SVG canvas (force / cluster \u2502\n \u2502 / bundle / lattice) \u2502\n \u2502 \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n```mdl\ncomponent Visualization\n desc: |\n Internal component that owns a single persistent SVG.Graph mount.\n Swaps the active GraphProjector when the variant changes, seeding the\n new projector with the previous layout so node positions tween smoothly.\n props:\n variant: ExplorerVariant\n model: SpaceGraphModel\n state:\n projector?: GraphProjector<SpaceGraphNode>\n actions:\n createProjector(variant: ExplorerVariant, prev?: GraphLayout) \u2192 GraphProjector\n createRenderNode(variant: ExplorerVariant) \u2192 RenderNode\n```\n\n## Operations\n\n```mdl\nop createGraph\n desc: |\n Creates a new Graph object scoped to a target space or collection.\n Derives a ViewModel from the database for the selected typename, then\n writes the object via SpaceOperation.AddObject.\n input:\n name?: string\n typename?: string # ECHO typename used to seed the initial view\n target: Space | Collection\n targetNodeId?: string\n output: GraphObject\n effects: [echo:write]\n note: |\n The typename is resolved through ViewModel.makeFromDatabase; the resulting\n View is stored as a Ref inside the Graph object.\n```\n\n```mdl\nop buildFilter\n desc: |\n Compiles a raw query string into a Filter via QueryBuilder.\n Pure \u2014 no side effects; result is passed to SpaceGraphModel.setFilter.\n input:\n raw: string\n output: Filter.Any\n errors:\n ParseError: raw string is not valid query syntax\n```\n\n## Features\n\n```mdl\nfeat F-1: Graph Object\n\n req F-1.1: A Graph object stores a name, a View ref, and a compiled QueryAST.\n req F-1.2:\n when: user creates a new graph\n then: op:createGraph derives a ViewModel from the chosen typename and writes the Graph to ECHO\n\n req F-1.3:\n when: Graph is persisted\n then: it appears in the space object list and can be opened as an article\n```\n\n```mdl\nfeat F-2: Live Graph Model\n\n req F-2.1:\n when: ExplorerArticle mounts with a valid Graph subject\n then: SpaceGraphModel is opened against the subject's database\n\n req F-2.2:\n when: user types a query in the toolbar\n then: op:buildFilter compiles the raw string; model.setFilter applied; SVG re-renders\n\n req F-2.3:\n when: Graph is unmounted\n then: SpaceGraphModel is closed and all subscriptions released\n\n req F-2.4:\n when: an ECHO object in the database changes\n then: SpaceGraphModel emits an update and SVG.Graph re-renders without full remount\n tags: [reactive, collaborative]\n```\n\n```mdl\nfeat F-3: Visualization Variants\n\n req F-3.1:\n when: variant tab is selected\n then: Visualization swaps projector; previous node x/y seed the new projector so positions tween\n\n req F-3.2:\n when: variant is force\n then: SVG.Zoom wrapper is mounted enabling pan/zoom drag interaction\n\n req F-3.3:\n when: variant is cluster or bundle\n then: no SVG.Zoom wrapper; leaves grouped by typename; radial labels fade in after tween\n\n req F-3.4:\n when: variant is lattice\n then: nodes rendered as small rounded rectangles sorted by typename then label\n\n req F-3.5:\n when: variant is cluster and user clicks a root or group node\n then: subtree toggles collapsed/expanded via GraphClusterProjector.toggleCollapsed\n```\n\n```mdl\nfeat F-4: Node Interaction\n\n req F-4.1:\n when: pointer enters a node\n then: DxAnchorActivate event dispatched with the object's DXN and label, kind: card\n\n req F-4.2:\n when: pointer leaves a node\n then: DxAnchorActivate cleared (onNodeHover called with null)\n\n req F-4.3:\n when: node has no underlying ECHO object (synthetic root / group)\n then: no preview dispatched; node rendered in neutral colour\n```\n\n## Acceptance\n\n```mdl\ntest T-1: Graph creation\n given: user opens the object creation dialog and selects Graph\n when: a typename is selected and the form submitted\n then:\n - op:createGraph runs without error\n - new Graph object visible in space object list\n - Graph.view references a valid View object\n```\n\n```mdl\ntest T-2: Article mounts model\n given: a Graph with a populated query\n when: ExplorerArticle is rendered with role === article\n then:\n - SpaceGraphModel is opened\n - SVG canvas renders nodes derived from the database\n - toolbar shows QueryEditor and variant tabs\n```\n\n```mdl\ntest T-3: Variant switch preserves positions\n given: force variant is active with nodes positioned\n when: user switches to cluster variant\n then:\n - projector is recreated from previous layout\n - nodes tween from old positions to cluster target positions\n - SVG.Zoom wrapper is absent in the new mount\n```\n\n```mdl\ntest T-4: Query filter updates graph\n given: ExplorerArticle is open with all objects visible\n when: user types a typename filter in QueryEditor\n then:\n - op:buildFilter returns a Filter without error\n - SpaceGraphModel.setFilter applied\n - only matching nodes remain visible in the SVG\n```\n\n```mdl\ntest T-5: Node hover preview\n given: force-directed graph with at least one ECHO object node\n when: pointer enters that node\n then:\n - DxAnchorActivate event fired with correct DXN\n - kind === card\n```\n\n```mdl\ntest T-6: Lattice sort order\n given: database contains objects of two typenames A and B\n when: lattice variant is active\n then:\n - all typename-A nodes appear before typename-B nodes (or vice-versa, consistent order)\n - within each group nodes are ordered alphabetically by label\n```\n\n```mdl\ntest T-7: Model closed on unmount\n given: ExplorerArticle is mounted and SpaceGraphModel is open\n when: component unmounts\n then:\n - SpaceGraphModel.close() is called\n - no lingering ECHO subscriptions remain\n```\n\n---\n\n## Appendix: Extension Definitions\n\nExtension block types used in this document are defined below using\nthe core `ext` primitive \u2014 the only construct the base language provides.\n\n```mdl\next type\n uri: org.dxos.mdl.type@1.0\n desc: A named data structure with typed fields and optional literals.\n fields:\n desc?: Prose\n fields?: FieldMap # name[?]: TypeExpr (# inline comment)\n literals?: UnionList # a | b | c\n extends?: TypeRef[]\n```\n\n```mdl\next feat\n uri: org.dxos.mdl.feat@1.0\n desc: A named feature grouping one or more requirements.\n fields:\n desc?: Prose\n req: RequirementList\n nesting: self # feat blocks may contain feat blocks\n```\n\n```mdl\next test\n uri: org.dxos.mdl.test@1.0\n desc: An acceptance scenario expressed as given / when / then steps.\n fields:\n given?: Step | Step[]\n when?: Step | Step[]\n then: Step | Step[]\n tags?: TagList\n```\n\n```mdl\next component\n uri: org.dxos.mdl.component@1.0\n desc: A UI component with props, internal state, slots, actions, and events.\n fields:\n desc?: Prose\n props?: FieldMap # external inputs (immutable inside component)\n state?: FieldMap # internal reactive state\n slots?: FieldMap # named ReactNode injection points\n actions?: ActionMap # methods the component exposes or handles\n emits?: EventMap # events the component raises to its parent\n layout?: CodeBlock # ASCII sketch of visual structure (non-normative)\n```\n\n```mdl\next op\n uri: org.dxos.mdl.op@1.0\n desc: |\n A named operation with typed inputs, outputs, and declared errors.\n Pure ops have no effects or requires. Effectful ops declare both.\n fields:\n desc?: Prose\n input?: FieldMap # named input parameters\n output?: TypeExpr # return type\n errors?: ErrorMap # name: Prose (when this error occurs)\n effects?: EffectList # echo:read | echo:write | http | fs | ...\n requires?: ServiceList # injected service dependencies\n note?: Prose # implementation guidance (non-normative)\n```\n"],
5
+ "mappings": ";AAIA,SAASA,cAAc;AACvB,SAASC,iBAAiB;AAE1B,SAASC,iBAAiBC,cAAcC,oBAAoB;AAC5D,SAASC,YAAY;AACrB,SAASC,oBAAoB;AAC7B,SAASC,aAAa;;;ACVtB;;;ADeO,IAAMC,iBAAiBC,OAAOC,OAAOC,IAAAA,EAAMC,KAChDC,UAAUC,sBAAsB;EAAEC,UAAUC;AAAa,CAAA,GACzDH,UAAUI,kBAAkB;EAAEF,UAAUG;AAAgB,CAAA,GACxDL,UAAUM,gBAAgB;EAAEC,QAAQ;IAACC,MAAMA;;AAAO,CAAA,GAClDR,UAAUS,iBAAiB;EAAEP,UAAUQ;AAAa,CAAA,GACpDV,UAAUW,sBAAsB;EAAEC;AAAa,CAAA,GAC/CZ,UAAUa,qBAAqB;EAC7BC,OAAO;IAAEC,UAAUjB,KAAKkB,QAAQC;IAAKC,MAAM;IAAcC,SAASC;IAAYC,UAAU;EAAoB;AAC9G,CAAA,GACAzB,OAAO0B,IAAI;AAGb,IAAA,yBAAe3B;",
6
+ "names": ["Plugin", "AppPlugin", "AppGraphBuilder", "CreateObject", "ReactSurface", "meta", "translations", "Graph", "ExplorerPlugin", "Plugin", "define", "meta", "pipe", "AppPlugin", "addCreateObjectModule", "activate", "CreateObject", "addAppGraphModule", "AppGraphBuilder", "addSchemaModule", "schema", "Graph", "addSurfaceModule", "ReactSurface", "addTranslationsModule", "translations", "addPluginAssetModule", "asset", "pluginId", "profile", "key", "path", "content", "pluginSpec", "mimeType", "make"]
7
+ }
@@ -1,28 +1,3 @@
1
- // src/components/Tree/types/types.ts
2
- var treeTypeToTreeNode = (tree, rootId = tree.root, visited = /* @__PURE__ */ new Set()) => {
3
- const node = tree.nodes[rootId];
4
- if (!node) {
5
- return void 0;
6
- }
7
- if (visited.has(rootId)) {
8
- return {
9
- id: rootId,
10
- label: labelOf(node),
11
- data: node.data
12
- };
13
- }
14
- visited.add(rootId);
15
- return {
16
- id: rootId,
17
- label: labelOf(node),
18
- data: node.data,
19
- children: node.children.map((childId) => treeTypeToTreeNode(tree, childId, visited)).filter((c) => Boolean(c))
20
- };
21
- };
22
- var labelOf = (node) => {
23
- return typeof node.data?.text === "string" ? node.data.text : void 0;
24
- };
25
-
26
1
  // src/components/Tree/types/tree.ts
27
2
  import * as Schema from "effect/Schema";
28
3
  import { DXN, Key, Obj, Ref, Type } from "@dxos/echo";
@@ -38,13 +13,14 @@ var TreeNodeType = Schema.Struct({
38
13
  })),
39
14
  ref: Schema.optional(Ref.Ref(TestSchema.Expando))
40
15
  }).pipe(Schema.mutable);
41
- var TreeType = Schema.Struct({
16
+ var TreeType = class extends Type.makeObject(DXN.make("org.dxos.type.tree", "0.1.0"))(Schema.Struct({
42
17
  root: Key.EntityId,
43
18
  nodes: Schema.mutable(Schema.Record({
44
19
  key: Key.EntityId,
45
20
  value: TreeNodeType
46
21
  }))
47
- }).pipe(Type.makeObject(DXN.make("org.dxos.type.tree", "0.1.0")));
22
+ })) {
23
+ };
48
24
  var Tree = class _Tree {
49
25
  static create = () => {
50
26
  const id = Key.EntityId.random();
@@ -96,7 +72,7 @@ var Tree = class _Tree {
96
72
  }
97
73
  getNode(id) {
98
74
  const node = this._tree.nodes[id];
99
- invariant(node, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 77, S: this, A: ["node", ""] });
75
+ invariant(node, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 78, S: this, A: ["node", ""] });
100
76
  return node;
101
77
  }
102
78
  /**
@@ -222,8 +198,8 @@ var Tree = class _Tree {
222
198
  * Move child node.
223
199
  */
224
200
  moveNode(node, from, to) {
225
- invariant(from >= 0 && from < node.children.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 197, S: this, A: ["from >= 0 && from < node.children.length", ""] });
226
- invariant(to >= 0 && to < node.children.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 198, S: this, A: ["to >= 0 && to < node.children.length", ""] });
201
+ invariant(from >= 0 && from < node.children.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 198, S: this, A: ["from >= 0 && from < node.children.length", ""] });
202
+ invariant(to >= 0 && to < node.children.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 199, S: this, A: ["to >= 0 && to < node.children.length", ""] });
227
203
  if (from === to) {
228
204
  return null;
229
205
  }
@@ -280,8 +256,35 @@ var Tree = class _Tree {
280
256
  }
281
257
  };
282
258
 
259
+ // src/components/Tree/types/types.ts
260
+ var treeTypeToTreeNode = (tree, rootId = tree.root, visited = /* @__PURE__ */ new Set()) => {
261
+ const node = tree.nodes[rootId];
262
+ if (!node) {
263
+ return void 0;
264
+ }
265
+ if (visited.has(rootId)) {
266
+ return {
267
+ id: rootId,
268
+ label: labelOf(node),
269
+ data: node.data
270
+ };
271
+ }
272
+ visited.add(rootId);
273
+ return {
274
+ id: rootId,
275
+ label: labelOf(node),
276
+ data: node.data,
277
+ children: node.children.map((childId) => treeTypeToTreeNode(tree, childId, visited)).filter((c) => Boolean(c))
278
+ };
279
+ };
280
+ var labelOf = (node) => {
281
+ return typeof node.data?.text === "string" ? node.data.text : void 0;
282
+ };
283
+
283
284
  export {
285
+ TreeNodeType,
286
+ TreeType,
284
287
  Tree,
285
288
  treeTypeToTreeNode
286
289
  };
287
- //# sourceMappingURL=chunk-7XUDLV6E.mjs.map
290
+ //# sourceMappingURL=chunk-EZ52JY7X.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/components/Tree/types/tree.ts", "../../../src/components/Tree/types/types.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { DXN, Key, Obj, Ref, Type } from '@dxos/echo';\nimport { TestSchema } from '@dxos/echo/testing';\nimport { invariant } from '@dxos/invariant';\n\n// TODO(burdon): Reconcile with @dxos/graph (i.e., common types).\n\nexport const TreeNodeType = Schema.Struct({\n id: Key.EntityId,\n children: Schema.mutable(Schema.Array(Key.EntityId)),\n data: Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.Any })),\n ref: Schema.optional(Ref.Ref(TestSchema.Expando)),\n}).pipe(Schema.mutable);\n\nexport type TreeNodeType = Schema.Schema.Type<typeof TreeNodeType>;\n\nexport class TreeType extends Type.makeObject<TreeType>(DXN.make('org.dxos.type.tree', '0.1.0'))(\n Schema.Struct({\n root: Key.EntityId,\n nodes: Schema.mutable(Schema.Record({ key: Key.EntityId, value: TreeNodeType })),\n }),\n) {}\n\n/**\n * Wrapper object for tree.\n */\nexport class Tree {\n static create = (): TreeType => {\n const id = Key.EntityId.random();\n return Obj.make(TreeType, {\n root: id,\n nodes: {\n [id]: {\n id,\n children: [],\n data: { text: '' }, // TODO(burdon): Generic.\n },\n },\n });\n };\n\n private _tree: TreeType;\n\n constructor(tree?: TreeType) {\n this._tree = tree ?? Tree.create();\n }\n\n get tree() {\n return this._tree;\n }\n\n // TODO(burdon): Make reactive.\n get size() {\n return Object.keys(this._tree.nodes).length;\n }\n\n get root() {\n return this.getNode(this._tree.root);\n }\n\n //\n // Traversal\n //\n\n /**\n * Recursively traverse the tree until the callback returns a value.\n */\n tranverse<T>(\n callback: (node: TreeNodeType, depth: number) => T | void,\n root: Key.EntityId = this._tree.root,\n depth = 0,\n ): T | void {\n const node = this._tree.nodes[root];\n const result = callback(node, depth);\n if (result !== undefined) {\n return result;\n }\n\n for (const childId of node.children) {\n const result = this.tranverse(callback, childId, depth + 1);\n if (result !== undefined) {\n return result;\n }\n }\n }\n\n getNode(id: Key.EntityId): TreeNodeType {\n const node = this._tree.nodes[id];\n invariant(node);\n return node;\n }\n\n /**\n * Get the children of a node.\n */\n getChildNodes(node: TreeNodeType): Array<TreeNodeType> {\n return node.children.map((id) => this.getNode(id));\n }\n\n /**\n * Get the parent of a node.\n */\n getParent(node: TreeNodeType): TreeNodeType | null {\n const parent = this.tranverse((n) => {\n if (n.children.includes(node.id)) {\n return n;\n }\n });\n\n return parent ?? null;\n }\n\n /**\n * Get the next node in the tree.\n */\n getNext(node: TreeNodeType, hierarchical = true): TreeNodeType | undefined {\n if (hierarchical && node.children.length) {\n // First child.\n return this.getChildNodes(node)[0];\n } else {\n const parent = this.getParent(node);\n if (parent) {\n const idx = this.getChildNodes(parent).findIndex(({ id }) => id === node.id);\n if (idx < parent.children.length - 1) {\n // Next sibling.\n return this.getNode(parent.children[idx + 1]);\n } else {\n // Get parent's next sibling.\n return this.getNext(parent, false);\n }\n }\n }\n }\n\n /**\n * Get the previous node in the tree.\n */\n getPrevious(node: TreeNodeType, hierarchical = true): TreeNodeType | undefined {\n const parent = this.getParent(node)!;\n const idx = this.getChildNodes(parent).findIndex(({ id }) => id === node.id);\n if (idx === 0) {\n if (hierarchical) {\n return parent;\n }\n } else {\n const previous = this.getNode(parent.children[idx - 1]);\n if (hierarchical && previous.children.length) {\n return this.getLastDescendent(previous);\n }\n\n return previous;\n }\n }\n\n /**\n * Get the last descendent of a node.\n */\n getLastDescendent(node: TreeNodeType): TreeNodeType | undefined {\n const children = this.getChildNodes(node);\n const last = children.length ? children[children.length - 1] : undefined;\n if (last) {\n return this.getLastDescendent(last);\n }\n\n return node;\n }\n\n //\n // Mutations\n //\n\n /**\n * Clear tree.\n */\n clear(): void {\n const root = this._tree.nodes[this._tree.root];\n root.children.length = 0;\n Obj.update(this._tree, (obj) => {\n obj.nodes = {\n [root.id]: root,\n };\n });\n }\n\n /**\n * Add node.\n */\n addNode(parent: TreeNodeType, node?: TreeNodeType, index?: number): TreeNodeType {\n if (!node) {\n const id = Key.EntityId.random();\n node = { id, children: [], data: { text: '' } }; // TODO(burdon): Generic.\n }\n\n const nodeToAdd = node;\n Obj.update(this._tree, (obj) => {\n obj.nodes[nodeToAdd.id] = nodeToAdd;\n parent.children.splice(index ?? parent.children.length, 0, nodeToAdd.id);\n });\n return node;\n }\n\n /**\n * Delete node.\n */\n deleteNode(parent: TreeNodeType, id: Key.EntityId): TreeNodeType | undefined {\n const node = this._tree.nodes[id];\n if (!node) {\n return undefined;\n }\n\n Obj.update(this._tree, (obj) => {\n delete obj.nodes[node.id];\n });\n const idx = parent.children.findIndex((child) => child === id);\n if (idx !== -1) {\n Obj.update(this._tree, () => {\n parent.children.splice(idx, 1);\n });\n }\n\n return node;\n }\n\n /**\n * Move child node.\n */\n moveNode(node: TreeNodeType, from: number, to: number): TreeNodeType | null {\n invariant(from >= 0 && from < node.children.length);\n invariant(to >= 0 && to < node.children.length);\n if (from === to) {\n return null;\n }\n\n const child = node.children[from];\n Obj.update(this._tree, () => {\n node.children.splice(from, 1);\n node.children.splice(to, 0, child);\n });\n return this.getNode(child);\n }\n\n /**\n * Indent node.\n */\n indentNode(node: TreeNodeType): void {\n const parent = this.getParent(node);\n if (!parent) {\n return;\n }\n\n const idx = parent.children.findIndex((child) => child === node.id);\n if (idx < 1 || idx >= parent.children.length) {\n return;\n }\n\n const previous = this.getNode(parent.children[idx - 1]);\n Obj.update(this._tree, () => {\n parent.children.splice(idx, 1);\n previous.children.push(node.id);\n });\n }\n\n /**\n * Unindent node.\n */\n unindentNode(node: TreeNodeType): void {\n const parent = this.getParent(node);\n if (!parent) {\n return;\n }\n\n const ancestor = this.getParent(parent);\n if (!ancestor) {\n return;\n }\n\n // Remove node from parent and get following siblings.\n const nodeIdx = parent.children.findIndex((id) => id === node.id);\n let rest: Key.EntityId[] = [];\n Obj.update(this._tree, () => {\n const removed = parent.children.splice(nodeIdx, parent.children.length - nodeIdx);\n rest = removed.slice(1); // Skip the node itself.\n });\n\n // Add to ancestor.\n const parentIdx = this.getChildNodes(ancestor).findIndex((n) => n.id === parent.id);\n Obj.update(this._tree, () => {\n ancestor.children.splice(parentIdx + 1, 0, node.id);\n });\n\n // Transplant following siblings to current node.\n Obj.update(this._tree, () => {\n node.children.push(...rest);\n });\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Key } from '@dxos/echo';\nimport { type TreeNode } from '@dxos/react-ui-graph';\n\nimport { type TreeType } from './tree';\n\n/**\n * Convert an ECHO `TreeType` (id-keyed node map) into a nested `TreeNode` hierarchy.\n * Returns `undefined` if the root id is missing — the tree is then incomplete and shouldn't render.\n */\nexport const treeTypeToTreeNode = (\n tree: TreeType,\n rootId: Key.EntityId = tree.root,\n visited: Set<string> = new Set(),\n): TreeNode | undefined => {\n const node = tree.nodes[rootId];\n if (!node) {\n return undefined;\n }\n if (visited.has(rootId)) {\n return { id: rootId, label: labelOf(node), data: node.data };\n }\n visited.add(rootId);\n\n return {\n id: rootId,\n label: labelOf(node),\n data: node.data,\n children: node.children\n .map((childId) => treeTypeToTreeNode(tree, childId, visited))\n .filter((c): c is TreeNode => Boolean(c)),\n };\n};\n\nconst labelOf = (node: { data: Record<string, any> }): string | undefined => {\n return typeof node.data?.text === 'string' ? node.data.text : undefined;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["Schema", "DXN", "Key", "Obj", "Ref", "Type", "TestSchema", "invariant", "children", "data", "String", "ref", "optional", "pipe", "TreeType", "makeObject", "make", "EntityId", "nodes", "Record", "key", "TreeNodeType", "id", "root", "_tree", "tree", "result", "callback", "node", "depth", "undefined", "childId", "getNode", "n", "getChildNodes", "parent", "getParent", "idx", "hierarchical", "getLastDescendent", "previous", "length", "last", "update", "obj", "nodeToAdd", "splice", "index", "findIndex", "to", "from", "child", "push", "removed", "rest", "slice", "ancestor", "parentIdx", "treeTypeToTreeNode", "tree", "rootId", "root", "visited", "Set", "node", "nodes", "undefined", "has", "id", "label", "labelOf", "data", "add", "children", "map", "childId", "filter", "c", "Boolean", "text"]
7
+ }
@@ -32,12 +32,12 @@ __export(Graph_exports, {
32
32
  make: () => make
33
33
  });
34
34
  import * as Schema2 from "effect/Schema";
35
- import { DXN, Annotation, Filter, Obj, Query, QueryAST, Ref, Type, View } from "@dxos/echo";
35
+ import { Annotation, DXN, Filter, Obj, Query, QueryAST, Ref, Type, View } from "@dxos/echo";
36
36
  import { FormInputAnnotation, LabelAnnotation } from "@dxos/echo/Annotation";
37
37
  import { ViewAnnotation } from "@dxos/schema";
38
- var GraphSchema = Schema2.Struct({
38
+ var Graph = class extends Type.makeObject(DXN.make("org.dxos.type.graph", "0.1.0"))(Schema2.Struct({
39
39
  name: Schema2.optional(Schema2.String),
40
- view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
40
+ view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false), Schema2.optional),
41
41
  query: Schema2.Struct({
42
42
  raw: Schema2.optional(Schema2.String),
43
43
  ast: QueryAST.Query
@@ -49,15 +49,15 @@ var GraphSchema = Schema2.Struct({
49
49
  ]), Annotation.IconAnnotation.set({
50
50
  icon: "ph--graph--regular",
51
51
  hue: "green"
52
- }), Type.makeObject(DXN.make("org.dxos.type.graph", "0.1.0")));
53
- var Graph = GraphSchema;
52
+ }))) {
53
+ };
54
54
  var make = ({ name, query = {
55
55
  raw: "",
56
56
  ast: Query.select(Filter.nothing()).ast
57
- }, view }) => {
57
+ }, view } = {}) => {
58
58
  return Obj.make(Graph, {
59
59
  name,
60
- view: Ref.make(view),
60
+ view: view && Ref.make(view),
61
61
  query
62
62
  });
63
63
  };
@@ -66,4 +66,4 @@ export {
66
66
  ExplorerAction_exports,
67
67
  Graph_exports
68
68
  };
69
- //# sourceMappingURL=chunk-YBCHBVCJ.mjs.map
69
+ //# sourceMappingURL=chunk-TTFPTHAQ.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/types/ExplorerAction.ts", "../../../src/types/Graph.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { TypeInputOptionsAnnotation } from '@dxos/plugin-space';\n\nexport const GraphProps = Schema.Struct({\n name: Schema.optional(Schema.String),\n // TODO(wittjosiah): This should be a query input instead.\n typename: Schema.String.pipe(\n Schema.annotations({ title: 'Select type' }),\n TypeInputOptionsAnnotation.set({\n location: ['database', 'runtime'],\n kind: ['user'],\n }),\n Schema.optional,\n ),\n});\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { Annotation, DXN, Filter, Obj, Query, QueryAST, Ref, Type, View } from '@dxos/echo';\nimport { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/Annotation';\nimport { ViewAnnotation } from '@dxos/schema';\n\nexport class Graph extends Type.makeObject<Graph>(DXN.make('org.dxos.type.graph', '0.1.0'))(\n Schema.Struct({\n name: Schema.optional(Schema.String),\n view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false), Schema.optional),\n query: Schema.Struct({\n raw: Schema.optional(Schema.String),\n ast: QueryAST.Query,\n }).pipe(FormInputAnnotation.set(false)),\n }).pipe(\n LabelAnnotation.set(['name']),\n ViewAnnotation.set(['view']),\n Annotation.IconAnnotation.set({ icon: 'ph--graph--regular', hue: 'green' }),\n ),\n) {}\n\ntype MakeProps = Omit<Partial<Obj.MakeProps<typeof Graph>>, 'view'> & {\n view?: View.View;\n};\n\n/**\n * Make a graph as a view of a data set.\n */\nexport const make = ({\n name,\n query = { raw: '', ast: Query.select(Filter.nothing()).ast },\n view,\n}: MakeProps = {}): Graph => {\n return Obj.make(Graph, { name, view: view && Ref.make(view), query });\n};\n"],
5
+ "mappings": ";;;;;AAAA;;;;AAIA,YAAYA,YAAY;AAExB,SAASC,kCAAkC;AAEpC,IAAMC,aAAoBC,cAAO;EACtCC,MAAaC,gBAAgBC,aAAM;;EAEnCC,UAAiBD,cAAOE,KACfC,mBAAY;IAAEC,OAAO;EAAc,CAAA,GAC1CT,2BAA2BU,IAAI;IAC7BC,UAAU;MAAC;MAAY;;IACvBC,MAAM;MAAC;;EACT,CAAA,GACOR,eAAQ;AAEnB,CAAA;;;ACnBA;;;;;AAIA,YAAYS,aAAY;AAExB,SAASC,YAAYC,KAAKC,QAAQC,KAAKC,OAAOC,UAAUC,KAAKC,MAAMC,YAAY;AAC/E,SAASC,qBAAqBC,uBAAuB;AACrD,SAASC,sBAAsB;AAExB,IAAMC,QAAN,cAAoBL,KAAKM,WAAkBZ,IAAIa,KAAK,uBAAuB,OAAA,CAAA,EACzEC,eAAO;EACZC,MAAaC,iBAAgBC,cAAM;EACnCC,MAAMb,IAAIA,IAAIE,KAAKA,IAAI,EAAEY,KAAKX,oBAAoBY,IAAI,KAAA,GAAeJ,gBAAQ;EAC7EK,OAAcP,eAAO;IACnBQ,KAAYN,iBAAgBC,cAAM;IAClCM,KAAKnB,SAASD;EAChB,CAAA,EAAGgB,KAAKX,oBAAoBY,IAAI,KAAA,CAAA;AAClC,CAAA,EAAGD,KACDV,gBAAgBW,IAAI;EAAC;CAAO,GAC5BV,eAAeU,IAAI;EAAC;CAAO,GAC3BrB,WAAWyB,eAAeJ,IAAI;EAAEK,MAAM;EAAsBC,KAAK;AAAQ,CAAA,CAAA,CAAA,EAAA;AAE1E;AASI,IAAMb,OAAO,CAAC,EACnBE,MACAM,QAAQ;EAAEC,KAAK;EAAIC,KAAKpB,MAAMwB,OAAO1B,OAAO2B,QAAO,CAAA,EAAIL;AAAI,GAC3DL,KAAI,IACS,CAAC,MAAC;AACf,SAAOhB,IAAIW,KAAKF,OAAO;IAAEI;IAAMG,MAAMA,QAAQb,IAAIQ,KAAKK,IAAAA;IAAOG;EAAM,CAAA;AACrE;",
6
+ "names": ["Schema", "TypeInputOptionsAnnotation", "GraphProps", "Struct", "name", "optional", "String", "typename", "pipe", "annotations", "title", "set", "location", "kind", "Schema", "Annotation", "DXN", "Filter", "Obj", "Query", "QueryAST", "Ref", "Type", "View", "FormInputAnnotation", "LabelAnnotation", "ViewAnnotation", "Graph", "makeObject", "make", "Struct", "name", "optional", "String", "view", "pipe", "set", "query", "raw", "ast", "IconAnnotation", "icon", "hue", "select", "nothing"]
7
+ }