@macrostrat/feedback-components 1.1.0 → 1.1.1

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 (58) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/esm/{feedback-components.7cd9b6cc.js → feedback-components.3b3a5357.js} +53 -30
  3. package/dist/esm/feedback-components.3b3a5357.js.map +1 -0
  4. package/dist/esm/{feedback-components.921dcd46.js → feedback-components.46a7a347.js} +42 -14
  5. package/dist/esm/feedback-components.46a7a347.js.map +1 -0
  6. package/dist/esm/{feedback-components.87533431.js → feedback-components.5509fab3.js} +5 -5
  7. package/dist/esm/{feedback-components.87533431.js.map → feedback-components.5509fab3.js.map} +1 -1
  8. package/dist/esm/{feedback-components.6a6c8af5.js → feedback-components.586103e8.js} +108 -82
  9. package/dist/esm/feedback-components.586103e8.js.map +1 -0
  10. package/dist/esm/{feedback-components.4359bc80.js → feedback-components.95dbe7d7.js} +13 -1
  11. package/dist/esm/feedback-components.95dbe7d7.js.map +1 -0
  12. package/dist/esm/{feedback-components.bf5f7cf7.js → feedback-components.fa1d3641.js} +29 -2
  13. package/dist/esm/feedback-components.fa1d3641.js.map +1 -0
  14. package/dist/esm/{feedback-components.b7d9b015.css → feedback-components.fb60c70d.css} +38 -14
  15. package/dist/esm/feedback-components.fb60c70d.css.map +1 -0
  16. package/dist/esm/index.d.ts +3 -82
  17. package/dist/esm/index.d.ts.map +1 -1
  18. package/dist/esm/index.js +1 -1
  19. package/dist/node/feedback-components.561466ac.js +2 -0
  20. package/dist/node/feedback-components.561466ac.js.map +1 -0
  21. package/dist/node/feedback-components.571ee23c.js +2 -0
  22. package/dist/node/feedback-components.571ee23c.js.map +1 -0
  23. package/dist/node/{feedback-components.e8aa70b8.js → feedback-components.a39f7653.js} +2 -2
  24. package/dist/node/{feedback-components.e8aa70b8.js.map → feedback-components.a39f7653.js.map} +1 -1
  25. package/dist/node/feedback-components.b7946db4.js +2 -0
  26. package/dist/node/feedback-components.b7946db4.js.map +1 -0
  27. package/dist/node/feedback-components.c459cc27.js +2 -0
  28. package/dist/node/feedback-components.c459cc27.js.map +1 -0
  29. package/dist/node/feedback-components.c88cb37f.css +2 -0
  30. package/dist/node/feedback-components.c88cb37f.css.map +1 -0
  31. package/dist/node/feedback-components.ec54a1e7.js +2 -0
  32. package/dist/node/feedback-components.ec54a1e7.js.map +1 -0
  33. package/dist/node/index.js +1 -1
  34. package/dist/node/index.js.map +1 -1
  35. package/package.json +3 -3
  36. package/src/feedback/edit-state.ts +41 -3
  37. package/src/feedback/feedback.module.sass +30 -10
  38. package/src/feedback/graph.ts +27 -10
  39. package/src/feedback/index.ts +146 -112
  40. package/src/feedback/text-visualizer.ts +43 -17
  41. package/dist/esm/feedback-components.4359bc80.js.map +0 -1
  42. package/dist/esm/feedback-components.6a6c8af5.js.map +0 -1
  43. package/dist/esm/feedback-components.7cd9b6cc.js.map +0 -1
  44. package/dist/esm/feedback-components.921dcd46.js.map +0 -1
  45. package/dist/esm/feedback-components.b7d9b015.css.map +0 -1
  46. package/dist/esm/feedback-components.bf5f7cf7.js.map +0 -1
  47. package/dist/node/feedback-components.15e1316d.js +0 -2
  48. package/dist/node/feedback-components.15e1316d.js.map +0 -1
  49. package/dist/node/feedback-components.65d8488e.js +0 -2
  50. package/dist/node/feedback-components.65d8488e.js.map +0 -1
  51. package/dist/node/feedback-components.6681dbde.js +0 -2
  52. package/dist/node/feedback-components.6681dbde.js.map +0 -1
  53. package/dist/node/feedback-components.77b6fc89.css +0 -2
  54. package/dist/node/feedback-components.77b6fc89.css.map +0 -1
  55. package/dist/node/feedback-components.7caa447a.js +0 -2
  56. package/dist/node/feedback-components.7caa447a.js.map +0 -1
  57. package/dist/node/feedback-components.e2f3c4b7.js +0 -2
  58. package/dist/node/feedback-components.e2f3c4b7.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format
4
4
  is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this
5
5
  project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.1.1] - 2025-07-01
8
+
9
+ - new text component, following same clicking rules as tree
10
+ - Entity panel updates
11
+ - Entity types are editable, deletable, and addable
12
+
7
13
  ## [1.1.0] - 2025-06-25
8
14
 
9
15
  Major updates by David Sklar to improve usability
@@ -1,24 +1,33 @@
1
- import {treeToGraph as $b79bf29960412ca7$export$8d9dbb7a64bf2a5e} from "./feedback-components.bf5f7cf7.js";
1
+ import {treeToGraph as $b79bf29960412ca7$export$8d9dbb7a64bf2a5e} from "./feedback-components.fa1d3641.js";
2
+ import "./feedback-components.fb60c70d.css";
3
+ import $phGch$feedbackcomponents95dbe7d7js from "./feedback-components.95dbe7d7.js";
2
4
  import {getTagStyle as $03d8811e9c9b360d$export$35baa338324d8550} from "./feedback-components.5df2a926.js";
3
5
  import $phGch$macrostrathyper from "@macrostrat/hyper";
4
6
  import {forceSimulation as $phGch$forceSimulation, forceLink as $phGch$forceLink, forceManyBody as $phGch$forceManyBody, forceCenter as $phGch$forceCenter, forceCollide as $phGch$forceCollide} from "d3-force";
5
7
  import {useState as $phGch$useState, useEffect as $phGch$useEffect} from "react";
6
- import {Spinner as $phGch$Spinner} from "@blueprintjs/core";
8
+ import {Spinner as $phGch$Spinner, Switch as $phGch$Switch} from "@blueprintjs/core";
7
9
  import {ErrorBoundary as $phGch$ErrorBoundary} from "@macrostrat/ui-components";
8
10
 
9
11
 
12
+ function $parcel$interopDefault(a) {
13
+ return a && a.__esModule ? a.default : a;
14
+ }
15
+
16
+
10
17
 
11
18
 
12
19
 
13
20
 
14
21
 
15
22
 
23
+ const $ff8c3e7f2bc22925$var$h = (0, $phGch$macrostrathyper).styled((0, ($parcel$interopDefault($phGch$feedbackcomponents95dbe7d7js))));
16
24
  function $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566(props) {
17
25
  // A graph view with react-flow
18
26
  // Get positions of nodes using force simulation
19
27
  const { tree: tree, width: width, height: height, dispatch: dispatch, selectedNodes: selectedNodes } = props;
20
28
  const [nodes, setNodes] = (0, $phGch$useState)(null);
21
29
  const [links, setLinks] = (0, $phGch$useState)(null);
30
+ const [showLabels, setShowLabels] = (0, $phGch$useState)(false);
22
31
  (0, $phGch$useEffect)(()=>{
23
32
  const { nodes: nodes, edges: edges } = (0, $b79bf29960412ca7$export$8d9dbb7a64bf2a5e)(tree);
24
33
  const nodesMap = new Map(nodes.map((d)=>[
@@ -49,22 +58,28 @@ function $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566(props) {
49
58
  width,
50
59
  height
51
60
  ]);
52
- if (nodes == null || links == null) return (0, $phGch$macrostrathyper)((0, $phGch$Spinner));
61
+ if (nodes == null || links == null) return $ff8c3e7f2bc22925$var$h((0, $phGch$Spinner));
53
62
  console.log("Graph", nodes, links, selectedNodes);
54
- return (0, $phGch$macrostrathyper)((0, $phGch$ErrorBoundary), {
63
+ return $ff8c3e7f2bc22925$var$h((0, $phGch$ErrorBoundary), {
55
64
  description: "An error occurred while rendering the graph view."
56
- }, (0, $phGch$macrostrathyper)("div.graph-view", {
65
+ }, $ff8c3e7f2bc22925$var$h("div.graph-view", {
57
66
  style: {
58
67
  width: width,
59
68
  height: height
60
69
  }
61
70
  }, [
62
- (0, $phGch$macrostrathyper)("svg", {
71
+ $ff8c3e7f2bc22925$var$h((0, $phGch$Switch), {
72
+ className: "show-labels-switch",
73
+ label: "Show Labels",
74
+ checked: showLabels,
75
+ onChange: (e)=>setShowLabels(e.target.checked)
76
+ }),
77
+ $ff8c3e7f2bc22925$var$h("svg", {
63
78
  width: width,
64
79
  height: height
65
80
  }, [
66
- (0, $phGch$macrostrathyper)("g.links", links.map((d)=>{
67
- return (0, $phGch$macrostrathyper)("line", {
81
+ $ff8c3e7f2bc22925$var$h("g.links", links.map((d)=>{
82
+ return $ff8c3e7f2bc22925$var$h("line", {
68
83
  x1: d.source.x,
69
84
  y1: d.source.y,
70
85
  x2: d.target.x,
@@ -72,7 +87,7 @@ function $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566(props) {
72
87
  stroke: "black"
73
88
  });
74
89
  })),
75
- (0, $phGch$macrostrathyper)("g.nodes", nodes.map((d)=>{
90
+ $ff8c3e7f2bc22925$var$h("g.nodes", nodes.map((d)=>{
76
91
  const active = selectedNodes.includes(d.id);
77
92
  const stroke = active ? "white" : "black";
78
93
  const highlighted = $ff8c3e7f2bc22925$var$isHighlighted(d.id, selectedNodes, nodes);
@@ -80,26 +95,34 @@ function $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566(props) {
80
95
  highlighted: highlighted,
81
96
  active: active
82
97
  });
83
- return (0, $phGch$macrostrathyper)("circle", {
84
- cx: d.x,
85
- cy: d.y,
86
- r: 5,
87
- fill: style.backgroundColor || "blue",
88
- onClick: (e)=>{
89
- e.stopPropagation();
90
- dispatch({
91
- type: "toggle-node-selected",
92
- payload: {
93
- ids: [
94
- d.id
95
- ]
96
- }
97
- });
98
- },
99
- className: active ? "selected" : "",
100
- stroke: stroke,
101
- strokeWidth: 2
102
- }, (0, $phGch$macrostrathyper)("title", d.name || `Node ${d.id}`));
98
+ return $ff8c3e7f2bc22925$var$h("g", [
99
+ $ff8c3e7f2bc22925$var$h("circle", {
100
+ cx: d.x,
101
+ cy: d.y,
102
+ r: 8,
103
+ fill: style.backgroundColor || "blue",
104
+ onClick: (e)=>{
105
+ e.stopPropagation();
106
+ dispatch({
107
+ type: "toggle-node-selected",
108
+ payload: {
109
+ ids: [
110
+ d.id
111
+ ]
112
+ }
113
+ });
114
+ },
115
+ className: active ? "selected" : "",
116
+ stroke: stroke,
117
+ strokeWidth: 2
118
+ }),
119
+ $ff8c3e7f2bc22925$var$h.if(showLabels)("text", {
120
+ x: d.x + 10,
121
+ y: d.y + 4,
122
+ className: "node-label"
123
+ }, d.name || `Node ${d.id}`),
124
+ $ff8c3e7f2bc22925$var$h.if(!showLabels)("title", d.name || `Node ${d.id}`)
125
+ ]);
103
126
  }))
104
127
  ])
105
128
  ]));
@@ -111,4 +134,4 @@ function $ff8c3e7f2bc22925$var$isHighlighted(id, selectedNodes, nodes) {
111
134
 
112
135
 
113
136
  export {$ff8c3e7f2bc22925$export$6a7fe3ef90e8d566 as GraphView};
114
- //# sourceMappingURL=feedback-components.7cd9b6cc.js.map
137
+ //# sourceMappingURL=feedback-components.3b3a5357.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["packages/feedback-components/src/feedback/graph.ts"],"sourcesContent":["import { TreeData } from \"./types\";\nimport { treeToGraph } from \"./edit-state\";\nimport styles from \"./feedback.module.sass\";\nimport hyper from \"@macrostrat/hyper\";\nimport {\n forceSimulation,\n SimulationNodeDatum,\n SimulationLinkDatum,\n forceCenter,\n forceLink,\n forceManyBody,\n forceCollide,\n} from \"d3-force\";\nimport { useEffect, useState } from \"react\";\nimport { Spinner, Switch } from \"@blueprintjs/core\";\nimport { ErrorBoundary } from \"@macrostrat/ui-components\";\nimport { getTagStyle } from \"../extractions\";\n\nconst h = hyper.styled(styles);\n\nexport function GraphView(props: {\n tree: TreeData[];\n width: number;\n height: number;\n dispatch: (action: any) => void;\n selectedNodes: number[];\n}) {\n // A graph view with react-flow\n // Get positions of nodes using force simulation\n const { tree, width, height, dispatch, selectedNodes } = props;\n\n const [nodes, setNodes] = useState<SimulationNodeDatum[]>(null);\n const [links, setLinks] = useState<SimulationLinkDatum[]>(null);\n const [showLabels, setShowLabels] = useState(false);\n\n useEffect(() => {\n const { nodes, edges } = treeToGraph(tree);\n\n const nodesMap = new Map<number, SimulationNodeDatum>(\n nodes.map((d) => [d.id, d]),\n );\n\n const links = edges.map((d) => {\n return {\n source: nodesMap.get(d.source),\n target: nodesMap.get(d.dest),\n strength: 1,\n };\n });\n\n const simulation = forceSimulation(nodes)\n .force(\"link\", forceLink(links))\n .force(\"charge\", forceManyBody().strength(-50))\n .force(\"center\", forceCenter(width / 2, height / 2))\n .force(\"collide\", forceCollide().radius(20))\n .on(\"tick\", () => {\n // Update the positions of the nodes\n // setNodes(nodes);\n console.log(\"Simulation tick\");\n })\n .on(\"end\", () => {\n // Update the positions of the nodes\n setNodes(nodes);\n setLinks(links);\n });\n\n return () => {\n simulation.stop();\n };\n }, [tree, width, height]);\n\n if (nodes == null || links == null) {\n return h(Spinner);\n }\n\n console.log(\"Graph\", nodes, links, selectedNodes);\n\n return h(\n ErrorBoundary,\n {\n description: \"An error occurred while rendering the graph view.\",\n },\n h(\"div.graph-view\", { style: { width, height } }, [\n h(Switch, {\n className: \"show-labels-switch\",\n label: \"Show Labels\",\n checked: showLabels,\n onChange: (e) => setShowLabels(e.target.checked),\n }),\n h(\"svg\", { width, height }, [\n h(\n \"g.links\",\n links.map((d) => {\n return h(\"line\", {\n x1: d.source.x,\n y1: d.source.y,\n x2: d.target.x,\n y2: d.target.y,\n stroke: \"black\",\n });\n }),\n ),\n h(\n \"g.nodes\",\n nodes.map((d) => {\n const active = selectedNodes.includes(d.id);\n const stroke = active ? \"white\" : \"black\";\n const highlighted = isHighlighted(d.id, selectedNodes, nodes);\n const style = getTagStyle(d.color, { highlighted, active });\n\n return h(\"g\", [\n h(\"circle\", {\n cx: d.x,\n cy: d.y,\n r: 8,\n fill: style.backgroundColor || \"blue\",\n onClick: (e) => {\n e.stopPropagation();\n dispatch({\n type: \"toggle-node-selected\",\n payload: { ids: [d.id] },\n });\n },\n className: active ? \"selected\" : \"\",\n stroke,\n strokeWidth: 2,\n }),\n h.if(showLabels)(\n \"text\",\n {\n x: d.x + 10,\n y: d.y + 4,\n className: \"node-label\",\n },\n d.name || `Node ${d.id}`,\n ),\n h.if(!showLabels)(\"title\", d.name || `Node ${d.id}`),\n ]);\n }),\n ),\n ]),\n ]),\n );\n}\n\nfunction isHighlighted(id: number, selectedNodes: number[], nodes: TreeData[]) {\n if (selectedNodes.length === 0) return true;\n return (\n selectedNodes.includes(id) ||\n nodes.some(\n (node) =>\n selectedNodes.includes(node.id) &&\n node.children.some((child) => child.id === id),\n )\n );\n}\n"],"names":[],"version":3,"file":"feedback-components.3b3a5357.js.map"}
@@ -1,5 +1,5 @@
1
- import "./feedback-components.b7d9b015.css";
2
- import $aogpP$feedbackcomponents4359bc80js from "./feedback-components.4359bc80.js";
1
+ import "./feedback-components.fb60c70d.css";
2
+ import $aogpP$feedbackcomponents95dbe7d7js from "./feedback-components.95dbe7d7.js";
3
3
  import {buildHighlights as $03d8811e9c9b360d$export$c4b91360064ad200, getTagStyle as $03d8811e9c9b360d$export$35baa338324d8550} from "./feedback-components.5df2a926.js";
4
4
  import $aogpP$macrostrathyper from "@macrostrat/hyper";
5
5
  import {useRef as $aogpP$useRef, useEffect as $aogpP$useEffect} from "react";
@@ -12,7 +12,7 @@ function $parcel$interopDefault(a) {
12
12
 
13
13
 
14
14
 
15
- const $156a3efbc315814c$var$h = (0, $aogpP$macrostrathyper).styled((0, ($parcel$interopDefault($aogpP$feedbackcomponents4359bc80js))));
15
+ const $156a3efbc315814c$var$h = (0, $aogpP$macrostrathyper).styled((0, ($parcel$interopDefault($aogpP$feedbackcomponents95dbe7d7js))));
16
16
  function $156a3efbc315814c$var$buildTags(highlights, selectedNodes) {
17
17
  let tags = [];
18
18
  // If entity ID has already been seen, don't add it again
@@ -51,7 +51,7 @@ function $156a3efbc315814c$var$isHighlighted(tag, selectedNodes) {
51
51
  }
52
52
  function $156a3efbc315814c$export$6e107db9091b8219(props) {
53
53
  // Convert input to tags
54
- const { text: text, selectedNodes: selectedNodes, nodes: nodes, dispatch: dispatch, lineHeight: lineHeight, allowOverlap: allowOverlap } = props;
54
+ const { text: text, selectedNodes: selectedNodes, nodes: nodes, dispatch: dispatch, allowOverlap: allowOverlap } = props;
55
55
  const allTags = $156a3efbc315814c$var$buildTags((0, $03d8811e9c9b360d$export$c4b91360064ad200)(nodes, null), selectedNodes);
56
56
  return $156a3efbc315814c$var$h("div.feedback-text-wrapper", {
57
57
  tabIndex: 0,
@@ -66,7 +66,6 @@ function $156a3efbc315814c$export$6e107db9091b8219(props) {
66
66
  }, $156a3efbc315814c$var$h($156a3efbc315814c$export$190465bec6b893be, {
67
67
  text: text,
68
68
  allTags: allTags,
69
- lineHeight: lineHeight,
70
69
  allowOverlap: allowOverlap,
71
70
  dispatch: dispatch,
72
71
  selectedNodes: selectedNodes
@@ -90,7 +89,13 @@ function $156a3efbc315814c$var$createTagFromSelection({ container: container })
90
89
  };
91
90
  }
92
91
  function $156a3efbc315814c$var$addTag({ tag: tag, dispatch: dispatch, text: text, allTags: allTags, allowOverlap: allowOverlap }) {
93
- const { start: start, end: end } = tag;
92
+ let { start: start, end: end } = tag;
93
+ // snap to text
94
+ if (text[end - 1] != " ") {
95
+ // double clicking word overselects by one, shouldn't increase to next word
96
+ while(start > 0 && /\w/.test(text[start - 1]))start--;
97
+ while(end < text.length && /\w/.test(text[end]))end++;
98
+ }
94
99
  let payload = {
95
100
  start: start,
96
101
  end: end,
@@ -172,9 +177,12 @@ function $156a3efbc315814c$var$renderNode(node, dispatch, selectedNodes, parentS
172
177
  if (typeof node === "string") return node;
173
178
  const { tag: tag, children: children } = node;
174
179
  const isSelected = selectedNodes?.includes(tag.id);
180
+ const showBorder = selectedNodes.length === 0 || isSelected;
175
181
  const style = {
176
182
  ...tag,
177
- zIndex: parentSelected ? -1 : 1
183
+ zIndex: parentSelected ? -1 : 1,
184
+ border: "1px solid " + (showBorder ? tag.color : "transparent"),
185
+ margin: "-1px"
178
186
  };
179
187
  let moveText = [];
180
188
  if (isSelected) {
@@ -189,8 +197,31 @@ function $156a3efbc315814c$var$renderNode(node, dispatch, selectedNodes, parentS
189
197
  style: style,
190
198
  onClick: (e)=>{
191
199
  e.stopPropagation();
192
- dispatch({
193
- type: "toggle-node-selected",
200
+ if (e.ctrlKey || e.metaKey || selectedNodes[0] === tag.id && selectedNodes.length === 1) {
201
+ // Toggle selection on ctrl/cmd click or when node is only selected node
202
+ e.stopPropagation();
203
+ dispatch({
204
+ type: "toggle-node-selected",
205
+ payload: {
206
+ ids: [
207
+ tag.id
208
+ ]
209
+ }
210
+ });
211
+ } else if (e.shiftKey && selectedNodes.length > 0) {
212
+ // Select range from last selected node to this one
213
+ const lastSelected = selectedNodes[selectedNodes.length - 1];
214
+ dispatch({
215
+ type: "select-range",
216
+ payload: {
217
+ ids: [
218
+ lastSelected,
219
+ tag.id
220
+ ]
221
+ }
222
+ });
223
+ } else dispatch({
224
+ type: "select-node",
194
225
  payload: {
195
226
  ids: [
196
227
  tag.id
@@ -201,7 +232,7 @@ function $156a3efbc315814c$var$renderNode(node, dispatch, selectedNodes, parentS
201
232
  }, isSelected ? moveText.flat() : children.map((child, i)=>$156a3efbc315814c$var$renderNode(child, dispatch, selectedNodes, isSelected)));
202
233
  }
203
234
  function $156a3efbc315814c$export$190465bec6b893be(props) {
204
- const { text: text, allTags: allTags = [], lineHeight: lineHeight, dispatch: dispatch, selectedNodes: selectedNodes, allowOverlap: allowOverlap } = props;
235
+ const { text: text, allTags: allTags = [], dispatch: dispatch, selectedNodes: selectedNodes, allowOverlap: allowOverlap } = props;
205
236
  const tree = $156a3efbc315814c$var$nestHighlights(text, allTags);
206
237
  const spanRef = (0, $aogpP$useRef)(null);
207
238
  (0, $aogpP$useEffect)(()=>{
@@ -229,13 +260,10 @@ function $156a3efbc315814c$export$190465bec6b893be(props) {
229
260
  allowOverlap
230
261
  ]);
231
262
  return $156a3efbc315814c$var$h("span", {
232
- style: {
233
- lineHeight: lineHeight
234
- },
235
263
  ref: spanRef
236
264
  }, tree.children.map((child, i)=>$156a3efbc315814c$var$renderNode(child, dispatch, selectedNodes, false)));
237
265
  }
238
266
 
239
267
 
240
268
  export {$156a3efbc315814c$export$6e107db9091b8219 as FeedbackText, $156a3efbc315814c$export$190465bec6b893be as HighlightedText};
241
- //# sourceMappingURL=feedback-components.921dcd46.js.map
269
+ //# sourceMappingURL=feedback-components.46a7a347.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["packages/feedback-components/src/feedback/text-visualizer.ts"],"sourcesContent":["import { AnnotateBlendTag } from \"react-text-annotate-blend\";\nimport { InternalEntity } from \"./types\";\nimport { TreeDispatch } from \"./edit-state\";\nimport styles from \"./feedback.module.sass\";\nimport hyper from \"@macrostrat/hyper\";\nimport { buildHighlights, getTagStyle } from \"../extractions\";\nimport { Highlight } from \"../extractions/types\";\nimport { useEffect, useRef } from \"react\";\n\nconst h = hyper.styled(styles);\n\nexport interface FeedbackTextProps {\n text: string;\n selectedNodes: number[];\n nodes: InternalEntity[];\n updateNodes: (nodes: string[]) => void;\n dispatch: TreeDispatch;\n lineHeight: string;\n allowOverlap?: boolean;\n}\n\nfunction buildTags(\n highlights: Highlight[],\n selectedNodes: number[],\n): AnnotateBlendTag[] {\n let tags: AnnotateBlendTag[] = [];\n // If entity ID has already been seen, don't add it again\n const entities = new Set<number>();\n\n for (const highlight of highlights) {\n // Don't add multiply-linked entities multiple times\n if (entities.has(highlight.id)) continue;\n\n const highlighted = isHighlighted(highlight, selectedNodes);\n const active = isActive(highlight, selectedNodes);\n const tagStyle = getTagStyle(highlight.backgroundColor, {\n highlighted,\n active,\n });\n\n const tag = {\n color: tagStyle.color,\n tagStyle: {\n display: \"none\",\n },\n markStyle: {\n backgroundColor: tagStyle.backgroundColor,\n },\n ...highlight,\n backgroundColor: tagStyle.backgroundColor,\n };\n\n tags.push(tag);\n\n entities.add(highlight.id);\n }\n\n return tags;\n}\n\nfunction isActive(tag: Highlight, selectedNodes: number[]) {\n return selectedNodes.includes(tag.id);\n}\n\nfunction isHighlighted(tag: Highlight, selectedNodes: number[]) {\n if (selectedNodes.length === 0) return true;\n return (\n (selectedNodes.includes(tag.id) ||\n tag.parents?.some((d) => selectedNodes.includes(d))) ??\n false\n );\n}\n\nexport function FeedbackText(props: FeedbackTextProps) {\n // Convert input to tags\n const { text, selectedNodes, nodes, dispatch, allowOverlap } = props;\n const allTags: AnnotateBlendTag[] = buildTags(\n buildHighlights(nodes, null),\n selectedNodes,\n );\n\n return h(\n \"div.feedback-text-wrapper\",\n {\n tabIndex: 0,\n onKeyDown: (e) => {\n if (e.key === \"Backspace\") {\n dispatch({\n type: \"delete-node\",\n payload: { ids: selectedNodes },\n });\n }\n },\n },\n h(HighlightedText, {\n text,\n allTags,\n allowOverlap,\n dispatch,\n selectedNodes,\n }),\n );\n}\n\nfunction createTagFromSelection({\n container,\n}: {\n container: HTMLElement | null;\n}) {\n const selection = window.getSelection();\n if (\n !selection ||\n selection.isCollapsed ||\n selection.rangeCount === 0 ||\n !container\n )\n return null;\n\n const range = selection.getRangeAt(0);\n\n if (\n !container.contains(range.startContainer) ||\n !container.contains(range.endContainer)\n ) {\n return null;\n }\n\n const preRange = document.createRange();\n preRange.setStart(container, 0);\n preRange.setEnd(range.startContainer, range.startOffset);\n const start = preRange.toString().length;\n\n const selectedText = range.toString();\n const end = start + selectedText.length;\n\n return {\n start,\n end,\n text: selectedText,\n };\n}\n\nfunction addTag({ tag, dispatch, text, allTags, allowOverlap }) {\n let { start, end } = tag;\n // snap to text\n if (text[end - 1] != \" \") {\n // double clicking word overselects by one, shouldn't increase to next word\n while (start > 0 && /\\w/.test(text[start - 1])) {\n start--;\n }\n while (end < text.length && /\\w/.test(text[end])) {\n end++;\n }\n }\n\n let payload = { start, end, text: text.slice(start, end) };\n\n if (payload.text.trim() === \"\") {\n console.log(\"Blank tag found, ignoring\");\n return;\n }\n\n const duplicate = allTags.find(\n (t) =>\n t.start === payload.start &&\n (t.end === payload.end || t.end === payload.end - 1),\n );\n\n if (duplicate) {\n console.log(\"Duplicate tag found, ignoring\");\n return;\n }\n\n if (payload.text.endsWith(\" \")) {\n payload.text = payload.text.slice(0, -1);\n payload.end -= 1;\n }\n\n const inside = allTags.some(\n (t) => t.start <= payload.start && t.end >= payload.end,\n );\n\n const overlap = allTags.some(\n (t) => t.start < payload.end && t.end > payload.start,\n );\n\n if ((inside || overlap) && !allowOverlap) {\n console.log(\"Tag is inside another tag, ignoring\");\n return;\n }\n\n dispatch({ type: \"create-node\", payload });\n}\n\nfunction nestHighlights(text: string, tags: AnnotateBlendTag[]) {\n const events: Array<{\n pos: number;\n type: \"start\" | \"end\";\n tag: AnnotateBlendTag;\n }> = [];\n\n for (const tag of tags) {\n events.push({ pos: tag.start, type: \"start\", tag });\n events.push({ pos: tag.end, type: \"end\", tag });\n }\n\n events.sort((a, b) => {\n if (a.pos !== b.pos) return a.pos - b.pos;\n if (a.type === \"end\" && b.type === \"start\") return -1;\n if (a.type === \"start\" && b.type === \"end\") return 1;\n return 0;\n });\n\n const root = { children: [], textStart: 0 };\n const stack = [root];\n let lastPos = 0;\n\n for (const { pos, type, tag } of events) {\n const parent = stack[stack.length - 1];\n\n if (pos > lastPos) {\n const slice = text.slice(lastPos, pos);\n parent.children.push(slice);\n }\n\n if (type === \"start\") {\n const newNode = { tag, children: [], textStart: pos };\n parent.children.push(newNode);\n stack.push(newNode);\n } else {\n stack.pop();\n }\n\n lastPos = pos;\n }\n\n if (lastPos < text.length) {\n stack[stack.length - 1].children.push(text.slice(lastPos));\n }\n\n return root;\n}\n\nfunction renderNode(\n node: any,\n dispatch: TreeDispatch,\n selectedNodes: number[],\n parentSelected: boolean,\n): any {\n if (typeof node === \"string\") return node;\n\n const { tag, children } = node;\n const isSelected = selectedNodes?.includes(tag.id);\n const showBorder = selectedNodes.length === 0 || isSelected;\n\n const style = {\n ...tag,\n zIndex: parentSelected ? -1 : 1,\n border: \"1px solid \" + (showBorder ? tag.color : \"transparent\"),\n margin: \"-1px\",\n };\n\n let moveText = [];\n if (isSelected) {\n for (const key in children) {\n if (Object.prototype.hasOwnProperty.call(children, key)) {\n const child = children[key];\n if (child?.tag) {\n moveText.push(child.children[0]);\n } else {\n moveText.push(child);\n }\n }\n }\n }\n\n return h(\n \"span\",\n {\n className: \"highlight\",\n style,\n onClick: (e: MouseEvent) => {\n e.stopPropagation();\n if (\n e.ctrlKey ||\n e.metaKey ||\n (selectedNodes[0] === tag.id && selectedNodes.length === 1)\n ) {\n // Toggle selection on ctrl/cmd click or when node is only selected node\n e.stopPropagation();\n dispatch({\n type: \"toggle-node-selected\",\n payload: { ids: [tag.id] },\n });\n } else if (e.shiftKey && selectedNodes.length > 0) {\n // Select range from last selected node to this one\n const lastSelected = selectedNodes[selectedNodes.length - 1];\n\n dispatch({\n type: \"select-range\",\n payload: { ids: [lastSelected, tag.id] },\n });\n } else {\n dispatch({\n type: \"select-node\",\n payload: { ids: [tag.id] },\n });\n }\n },\n },\n isSelected\n ? moveText.flat()\n : children.map((child: any, i: number) =>\n renderNode(child, dispatch, selectedNodes, isSelected),\n ),\n );\n}\n\nexport function HighlightedText(props: {\n text: string;\n allTags: AnnotateBlendTag[];\n lineHeight: string;\n allowOverlap?: boolean;\n dispatch: TreeDispatch;\n selectedNodes: number[];\n}) {\n const { text, allTags = [], dispatch, selectedNodes, allowOverlap } = props;\n\n const tree = nestHighlights(text, allTags);\n\n const spanRef = useRef<HTMLSpanElement>(null);\n\n useEffect(() => {\n const handleMouseUp = () => {\n const tag = createTagFromSelection({ container: spanRef.current });\n if (!tag) return;\n addTag({ tag, dispatch, text, allTags, allowOverlap });\n };\n\n document.addEventListener(\"mouseup\", handleMouseUp);\n return () => {\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [text, allTags, dispatch, allowOverlap]);\n\n return h(\n \"span\",\n { ref: spanRef },\n tree.children.map((child: any, i: number) =>\n renderNode(child, dispatch, selectedNodes, false),\n ),\n );\n}\n"],"names":[],"version":3,"file":"feedback-components.46a7a347.js.map"}
@@ -1,7 +1,7 @@
1
1
  import {EntityTag as $03d8811e9c9b360d$export$117e56c71b172cde} from "./feedback-components.5df2a926.js";
2
- import {useTreeDispatch as $b79bf29960412ca7$export$e1068f2d1c68f87e} from "./feedback-components.bf5f7cf7.js";
3
- import "./feedback-components.b7d9b015.css";
4
- import $gIldz$feedbackcomponents4359bc80js from "./feedback-components.4359bc80.js";
2
+ import {useTreeDispatch as $b79bf29960412ca7$export$e1068f2d1c68f87e} from "./feedback-components.fa1d3641.js";
3
+ import "./feedback-components.fb60c70d.css";
4
+ import $gIldz$feedbackcomponents95dbe7d7js from "./feedback-components.95dbe7d7.js";
5
5
  import $gIldz$macrostrathyper from "@macrostrat/hyper";
6
6
 
7
7
 
@@ -12,7 +12,7 @@ function $parcel$interopDefault(a) {
12
12
 
13
13
 
14
14
 
15
- const $b6b9741bf83336eb$var$h = (0, $gIldz$macrostrathyper).styled((0, ($parcel$interopDefault($gIldz$feedbackcomponents4359bc80js))));
15
+ const $b6b9741bf83336eb$var$h = (0, $gIldz$macrostrathyper).styled((0, ($parcel$interopDefault($gIldz$feedbackcomponents95dbe7d7js))));
16
16
  function $b6b9741bf83336eb$var$isSelected(searchNode, treeNode) {
17
17
  return searchNode.id == treeNode.id;
18
18
  // We could also select children of the search node here if we wanted to
@@ -61,4 +61,4 @@ var $b6b9741bf83336eb$export$2e2bcd8739ae039 = $b6b9741bf83336eb$var$Node;
61
61
 
62
62
 
63
63
  export {$b6b9741bf83336eb$export$2e2bcd8739ae039 as default};
64
- //# sourceMappingURL=feedback-components.87533431.js.map
64
+ //# sourceMappingURL=feedback-components.5509fab3.js.map
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;;;;;;AAOA,MAAM,0BAAI,CAAA,GAAA,sBAAI,EAAE,MAAM,CAAC,CAAA,GAAA,8EAAK;AAE5B,SAAS,iCAAW,UAAoB,EAAE,QAAkB;IAC1D,OAAO,WAAW,EAAE,IAAI,SAAS,EAAE;AACnC,wEAAwE;AAC1E;AAEA,SAAS,wCAAkB,IAAuB,EAAE,IAAuB;IACzE,gFAAgF;IAChF,IAAI,KAAK,aAAa,CAAC,MAAM,IAAI,GAC/B,OAAO;IAGT,KAAK,MAAM,gBAAgB,KAAK,aAAa,CAAE;QAC7C,IAAI,iCAAW,KAAK,IAAI,EAAE,aAAa,IAAI,GACzC,OAAO;IAEX;IAEA,0CAA0C;IAC1C,IAAI,KAAK,MAAM,IAAI,QAAQ,wCAAkB,KAAK,MAAM,EAAE,OACxD,OAAO;IAGT,OAAO;AACT;AAEA,SAAS,mCAAa,IAAuB,EAAE,IAAuB;IACpE,KAAK,MAAM,gBAAgB,KAAK,aAAa,CAAE;QAC7C,IAAI,iCAAW,KAAK,IAAI,EAAE,aAAa,IAAI,GACzC,OAAO;IAEX;IACA,OAAO;AACT;AAEA,SAAS,2BAAK,QAAE,IAAI,SAAE,KAAK,cAAE,UAAU,QAAE,IAAI,kBAAE,cAAc,EAAO;IAClE,IAAI,cAAuB,wCAAkB,MAAM;IACnD,IAAI,SAAkB,mCAAa,MAAM;IAEzC,MAAM,WAAW,CAAA,GAAA,yCAAc;IAE/B,8DAA8D;IAE9D,IAAI,CAAC,KAAK,IAAI,EAAE,MACd,KAAK,IAAI,CAAC,IAAI,GAAG;QAAE,MAAM;QAAQ,OAAO;IAAoB;IAG9D,OAAO,wBACL,YACA;eAAE;QAAO,KAAK;IAAW,GACzB,wBAAE,CAAA,GAAA,yCAAQ,GAAG;QACX,MAAM,KAAK,IAAI;gBACf;qBACA;wBACA;QACA;YACE,SAAS;gBAAE,MAAM;YAA8B;QACjD;IACF;AAEJ;IAEA,2CAAe","sources":["packages/feedback-components/src/feedback/node.ts"],"sourcesContent":["import { NodeApi, TreeApi } from \"react-arborist\";\nimport { TreeData } from \"./types\";\nimport { EntityTag } from \"../extractions\";\nimport { useTreeDispatch } from \"./edit-state\";\nimport styles from \"./feedback.module.sass\";\nimport hyper from \"@macrostrat/hyper\";\n\nconst h = hyper.styled(styles);\n\nfunction isSelected(searchNode: TreeData, treeNode: TreeData) {\n return searchNode.id == treeNode.id;\n // We could also select children of the search node here if we wanted to\n}\n\nfunction isNodeHighlighted(node: NodeApi<TreeData>, tree: TreeApi<TreeData>) {\n // We treat no selection as all nodes being active. We may add some nuance later\n if (tree.selectedNodes.length == 0) {\n return true;\n }\n\n for (const selectedNode of tree.selectedNodes) {\n if (isSelected(node.data, selectedNode.data)) {\n return true;\n }\n }\n\n // Check if the parent node is highlighted\n if (node.parent != null && isNodeHighlighted(node.parent, tree)) {\n return true;\n }\n\n return false;\n}\n\nfunction isNodeActive(node: NodeApi<TreeData>, tree: TreeApi<TreeData>) {\n for (const selectedNode of tree.selectedNodes) {\n if (isSelected(node.data, selectedNode.data)) {\n return true;\n }\n }\n return false;\n}\n\nfunction Node({ node, style, dragHandle, tree, matchComponent }: any) {\n let highlighted: boolean = isNodeHighlighted(node, tree);\n let active: boolean = isNodeActive(node, tree);\n\n const dispatch = useTreeDispatch();\n\n // console.log(\"Node render\", node.data, highlighted, active);\n\n if (!node.data?.type) {\n node.data.type = { name: \"lith\", color: \"rgb(107, 255, 91)\" };\n }\n\n return h(\n \"div.node\",\n { style, ref: dragHandle },\n h(EntityTag, {\n data: node.data,\n active,\n highlighted,\n matchComponent,\n onClickType() {\n dispatch({ type: \"toggle-entity-type-selector\" });\n },\n }),\n );\n}\n\nexport default Node;\n"],"names":[],"version":3,"file":"feedback-components.87533431.js.map"}
1
+ {"mappings":";;;;;;;;;;;;;;AAOA,MAAM,0BAAI,CAAA,GAAA,sBAAI,EAAE,MAAM,CAAC,CAAA,GAAA,8EAAK;AAE5B,SAAS,iCAAW,UAAoB,EAAE,QAAkB;IAC1D,OAAO,WAAW,EAAE,IAAI,SAAS,EAAE;AACnC,wEAAwE;AAC1E;AAEA,SAAS,wCAAkB,IAAuB,EAAE,IAAuB;IACzE,gFAAgF;IAChF,IAAI,KAAK,aAAa,CAAC,MAAM,IAAI,GAC/B,OAAO;IAGT,KAAK,MAAM,gBAAgB,KAAK,aAAa,CAAE;QAC7C,IAAI,iCAAW,KAAK,IAAI,EAAE,aAAa,IAAI,GACzC,OAAO;IAEX;IAEA,0CAA0C;IAC1C,IAAI,KAAK,MAAM,IAAI,QAAQ,wCAAkB,KAAK,MAAM,EAAE,OACxD,OAAO;IAGT,OAAO;AACT;AAEA,SAAS,mCAAa,IAAuB,EAAE,IAAuB;IACpE,KAAK,MAAM,gBAAgB,KAAK,aAAa,CAAE;QAC7C,IAAI,iCAAW,KAAK,IAAI,EAAE,aAAa,IAAI,GACzC,OAAO;IAEX;IACA,OAAO;AACT;AAEA,SAAS,2BAAK,QAAE,IAAI,SAAE,KAAK,cAAE,UAAU,QAAE,IAAI,kBAAE,cAAc,EAAO;IAClE,IAAI,cAAuB,wCAAkB,MAAM;IACnD,IAAI,SAAkB,mCAAa,MAAM;IAEzC,MAAM,WAAW,CAAA,GAAA,yCAAc;IAE/B,8DAA8D;IAE9D,IAAI,CAAC,KAAK,IAAI,EAAE,MACd,KAAK,IAAI,CAAC,IAAI,GAAG;QAAE,MAAM;QAAQ,OAAO;IAAoB;IAG9D,OAAO,wBACL,YACA;eAAE;QAAO,KAAK;IAAW,GACzB,wBAAE,CAAA,GAAA,yCAAQ,GAAG;QACX,MAAM,KAAK,IAAI;gBACf;qBACA;wBACA;QACA;YACE,SAAS;gBAAE,MAAM;YAA8B;QACjD;IACF;AAEJ;IAEA,2CAAe","sources":["packages/feedback-components/src/feedback/node.ts"],"sourcesContent":["import { NodeApi, TreeApi } from \"react-arborist\";\nimport { TreeData } from \"./types\";\nimport { EntityTag } from \"../extractions\";\nimport { useTreeDispatch } from \"./edit-state\";\nimport styles from \"./feedback.module.sass\";\nimport hyper from \"@macrostrat/hyper\";\n\nconst h = hyper.styled(styles);\n\nfunction isSelected(searchNode: TreeData, treeNode: TreeData) {\n return searchNode.id == treeNode.id;\n // We could also select children of the search node here if we wanted to\n}\n\nfunction isNodeHighlighted(node: NodeApi<TreeData>, tree: TreeApi<TreeData>) {\n // We treat no selection as all nodes being active. We may add some nuance later\n if (tree.selectedNodes.length == 0) {\n return true;\n }\n\n for (const selectedNode of tree.selectedNodes) {\n if (isSelected(node.data, selectedNode.data)) {\n return true;\n }\n }\n\n // Check if the parent node is highlighted\n if (node.parent != null && isNodeHighlighted(node.parent, tree)) {\n return true;\n }\n\n return false;\n}\n\nfunction isNodeActive(node: NodeApi<TreeData>, tree: TreeApi<TreeData>) {\n for (const selectedNode of tree.selectedNodes) {\n if (isSelected(node.data, selectedNode.data)) {\n return true;\n }\n }\n return false;\n}\n\nfunction Node({ node, style, dragHandle, tree, matchComponent }: any) {\n let highlighted: boolean = isNodeHighlighted(node, tree);\n let active: boolean = isNodeActive(node, tree);\n\n const dispatch = useTreeDispatch();\n\n // console.log(\"Node render\", node.data, highlighted, active);\n\n if (!node.data?.type) {\n node.data.type = { name: \"lith\", color: \"rgb(107, 255, 91)\" };\n }\n\n return h(\n \"div.node\",\n { style, ref: dragHandle },\n h(EntityTag, {\n data: node.data,\n active,\n highlighted,\n matchComponent,\n onClickType() {\n dispatch({ type: \"toggle-entity-type-selector\" });\n },\n }),\n );\n}\n\nexport default Node;\n"],"names":[],"version":3,"file":"feedback-components.5509fab3.js.map"}
@@ -1,18 +1,17 @@
1
- import "./feedback-components.b7d9b015.css";
2
- import $bvJLP$feedbackcomponents4359bc80js from "./feedback-components.4359bc80.js";
3
- import $b6b9741bf83336eb$export$2e2bcd8739ae039 from "./feedback-components.87533431.js";
4
- import {FeedbackText as $156a3efbc315814c$export$6e107db9091b8219} from "./feedback-components.921dcd46.js";
5
- import {ModelInfo as $03d8811e9c9b360d$export$4eb2a0ce903ce967} from "./feedback-components.5df2a926.js";
6
- import {TreeDispatchContext as $b79bf29960412ca7$export$e5ce04c5b3f58533, treeToGraph as $b79bf29960412ca7$export$8d9dbb7a64bf2a5e, useUpdatableTree as $b79bf29960412ca7$export$911bb4b9c8065d3d} from "./feedback-components.bf5f7cf7.js";
1
+ import "./feedback-components.fb60c70d.css";
2
+ import $bvJLP$feedbackcomponents95dbe7d7js from "./feedback-components.95dbe7d7.js";
3
+ import $b6b9741bf83336eb$export$2e2bcd8739ae039 from "./feedback-components.5509fab3.js";
4
+ import {FeedbackText as $156a3efbc315814c$export$6e107db9091b8219} from "./feedback-components.46a7a347.js";
5
+ import {getTagStyle as $03d8811e9c9b360d$export$35baa338324d8550, ModelInfo as $03d8811e9c9b360d$export$4eb2a0ce903ce967} from "./feedback-components.5df2a926.js";
6
+ import {TreeDispatchContext as $b79bf29960412ca7$export$e5ce04c5b3f58533, treeToGraph as $b79bf29960412ca7$export$8d9dbb7a64bf2a5e, useUpdatableTree as $b79bf29960412ca7$export$911bb4b9c8065d3d} from "./feedback-components.fa1d3641.js";
7
7
  import {OmniboxSelector as $fda9ef5406c1cfb4$export$d8660660a589068c} from "./feedback-components.ad9f284e.js";
8
- import {GraphView as $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566} from "./feedback-components.7cd9b6cc.js";
8
+ import {GraphView as $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566} from "./feedback-components.3b3a5357.js";
9
9
  import $bvJLP$macrostrathyper from "@macrostrat/hyper";
10
10
  import {Tree as $bvJLP$Tree} from "react-arborist";
11
11
  import {useState as $bvJLP$useState, useRef as $bvJLP$useRef, useCallback as $bvJLP$useCallback, useEffect as $bvJLP$useEffect} from "react";
12
12
  import {SegmentedControl as $bvJLP$SegmentedControl, Card as $bvJLP$Card, ButtonGroup as $bvJLP$ButtonGroup, Divider as $bvJLP$Divider, Icon as $bvJLP$Icon, Overlay2 as $bvJLP$Overlay2, Popover as $bvJLP$Popover} from "@blueprintjs/core";
13
13
  import {ErrorBoundary as $bvJLP$ErrorBoundary, FlexRow as $bvJLP$FlexRow, CancelButton as $bvJLP$CancelButton, SaveButton as $bvJLP$SaveButton, useInDarkMode as $bvJLP$useInDarkMode} from "@macrostrat/ui-components";
14
14
  import $bvJLP$useelementdimensions from "use-element-dimensions";
15
- import {asChromaColor as $bvJLP$asChromaColor} from "@macrostrat/color-utils";
16
15
  import {ColorPicker as $bvJLP$ColorPicker} from "@macrostrat/data-sheet";
17
16
 
18
17
 
@@ -33,8 +32,7 @@ function $parcel$interopDefault(a) {
33
32
 
34
33
 
35
34
 
36
-
37
- const $71d20dff35996763$var$h = (0, $bvJLP$macrostrathyper).styled((0, ($parcel$interopDefault($bvJLP$feedbackcomponents4359bc80js))));
35
+ const $71d20dff35996763$var$h = (0, $bvJLP$macrostrathyper).styled((0, ($parcel$interopDefault($bvJLP$feedbackcomponents95dbe7d7js))));
38
36
  function $71d20dff35996763$var$setsAreTheSame(a, b) {
39
37
  if (a.size !== b.size) return false;
40
38
  for (const item of a){
@@ -42,60 +40,78 @@ function $71d20dff35996763$var$setsAreTheSame(a, b) {
42
40
  }
43
41
  return true;
44
42
  }
45
- function $71d20dff35996763$export$a90600c9da52b40c({ entities: entities = [], text: text, model: model, entityTypes: entityTypes, matchComponent: matchComponent, onSave: onSave, lineHeight: lineHeight, allowOverlap: allowOverlap }) {
43
+ function $71d20dff35996763$export$a90600c9da52b40c({ entities: entities = [], text: text, model: model, entityTypes: entityTypes, matchComponent: matchComponent, onSave: onSave, allowOverlap: allowOverlap }) {
46
44
  // Get the input arguments
47
45
  const [state, dispatch] = (0, $b79bf29960412ca7$export$911bb4b9c8065d3d)(entities.map($71d20dff35996763$var$processEntity), entityTypes);
48
46
  const { selectedNodes: selectedNodes, tree: tree, selectedEntityType: selectedEntityType, isSelectingEntityType: isSelectingEntityType, entityTypesMap: entityTypesMap } = state;
49
47
  const [{ width: width, height: height }, ref] = (0, $bvJLP$useelementdimensions)();
50
- return $71d20dff35996763$var$h((0, $b79bf29960412ca7$export$e5ce04c5b3f58533).Provider, {
51
- value: dispatch
52
- }, [
53
- $71d20dff35996763$var$h((0, $bvJLP$ErrorBoundary), {
54
- description: "An error occurred while rendering the feedback text component."
55
- }, $71d20dff35996763$var$h((0, $156a3efbc315814c$export$6e107db9091b8219), {
56
- text: text,
57
- dispatch: dispatch,
58
- // @ts-ignore
59
- nodes: tree,
60
- selectedNodes: selectedNodes,
61
- lineHeight: lineHeight,
62
- allowOverlap: allowOverlap
63
- })),
64
- $71d20dff35996763$var$h((0, $bvJLP$FlexRow), {
65
- alignItems: "baseline",
66
- justifyContent: "space-between"
48
+ return $71d20dff35996763$var$h("div.page-wrapper", [
49
+ $71d20dff35996763$var$h("div.feedback-container", $71d20dff35996763$var$h((0, $b79bf29960412ca7$export$e5ce04c5b3f58533).Provider, {
50
+ value: dispatch
67
51
  }, [
68
- $71d20dff35996763$var$h((0, $03d8811e9c9b360d$export$4eb2a0ce903ce967), {
69
- data: model
70
- }),
71
- $71d20dff35996763$var$h((0, $bvJLP$SegmentedControl), {
72
- options: [
73
- {
74
- label: "Tree",
75
- value: "tree"
76
- },
77
- {
78
- label: "Graph",
79
- value: "graph"
52
+ $71d20dff35996763$var$h((0, $bvJLP$ErrorBoundary), {
53
+ description: "An error occurred while rendering the feedback text component."
54
+ }, $71d20dff35996763$var$h((0, $156a3efbc315814c$export$6e107db9091b8219), {
55
+ text: text,
56
+ dispatch: dispatch,
57
+ // @ts-ignore
58
+ nodes: tree,
59
+ selectedNodes: selectedNodes,
60
+ allowOverlap: allowOverlap
61
+ })),
62
+ $71d20dff35996763$var$h((0, $bvJLP$FlexRow), {
63
+ alignItems: "baseline",
64
+ justifyContent: "space-between"
65
+ }, [
66
+ $71d20dff35996763$var$h((0, $03d8811e9c9b360d$export$4eb2a0ce903ce967), {
67
+ data: model
68
+ }),
69
+ $71d20dff35996763$var$h((0, $bvJLP$SegmentedControl), {
70
+ options: [
71
+ {
72
+ label: "Tree",
73
+ value: "tree"
74
+ },
75
+ {
76
+ label: "Graph",
77
+ value: "graph"
78
+ }
79
+ ],
80
+ value: state.viewMode,
81
+ small: true,
82
+ onValueChange (value) {
83
+ console.log("Setting view mode", value);
84
+ dispatch({
85
+ type: "set-view-mode",
86
+ payload: value
87
+ });
80
88
  }
81
- ],
82
- value: state.viewMode,
83
- small: true,
84
- onValueChange (value) {
85
- console.log("Setting view mode", value);
86
- dispatch({
87
- type: "set-view-mode",
88
- payload: value
89
- });
90
- }
91
- })
92
- ]),
93
- $71d20dff35996763$var$h("div.entity-panel", {
94
- ref: ref
95
- }, [
96
- $71d20dff35996763$var$h((0, $bvJLP$Card), {
97
- className: "control-panel"
89
+ })
90
+ ]),
91
+ $71d20dff35996763$var$h("div.entity-panel", {
92
+ ref: ref
98
93
  }, [
94
+ $71d20dff35996763$var$h.if(state.viewMode == "tree")($71d20dff35996763$var$ManagedSelectionTree, {
95
+ selectedNodes: selectedNodes,
96
+ dispatch: dispatch,
97
+ tree: tree,
98
+ width: width,
99
+ height: height,
100
+ matchComponent: matchComponent
101
+ }),
102
+ $71d20dff35996763$var$h.if(state.viewMode == "graph")((0, $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566), {
103
+ tree: tree,
104
+ width: width,
105
+ height: height,
106
+ dispatch: dispatch,
107
+ selectedNodes: selectedNodes
108
+ })
109
+ ])
110
+ ])),
111
+ $71d20dff35996763$var$h((0, $bvJLP$Card), {
112
+ className: "control-panel"
113
+ }, [
114
+ $71d20dff35996763$var$h("div.control-content", [
99
115
  $71d20dff35996763$var$h((0, $bvJLP$ButtonGroup), {
100
116
  vertical: true,
101
117
  fill: true,
@@ -137,22 +153,7 @@ function $71d20dff35996763$export$a90600c9da52b40c({ entities: entities = [], te
137
153
  payload: isOpen
138
154
  })
139
155
  })
140
- ]),
141
- $71d20dff35996763$var$h.if(state.viewMode == "tree")($71d20dff35996763$var$ManagedSelectionTree, {
142
- selectedNodes: selectedNodes,
143
- dispatch: dispatch,
144
- tree: tree,
145
- width: width,
146
- height: height,
147
- matchComponent: matchComponent
148
- }),
149
- $71d20dff35996763$var$h.if(state.viewMode == "graph")((0, $ff8c3e7f2bc22925$export$6a7fe3ef90e8d566), {
150
- tree: tree,
151
- width: width,
152
- height: height,
153
- dispatch: dispatch,
154
- selectedNodes: selectedNodes
155
- })
156
+ ])
156
157
  ])
157
158
  ]);
158
159
  }
@@ -240,18 +241,39 @@ function $71d20dff35996763$var$ManagedSelectionTree(props) {
240
241
  function handleClick() {
241
242
  clickedRef.current = true;
242
243
  }
244
+ const ctrlPressedRef = (0, $bvJLP$useRef)(false);
245
+ (0, $bvJLP$useEffect)(()=>{
246
+ const down = (e)=>{
247
+ if (e.ctrlKey || e.metaKey) ctrlPressedRef.current = true;
248
+ };
249
+ const up = ()=>ctrlPressedRef.current = false;
250
+ window.addEventListener("keydown", down);
251
+ window.addEventListener("keyup", up);
252
+ return ()=>{
253
+ window.removeEventListener("keydown", down);
254
+ window.removeEventListener("keyup", up);
255
+ };
256
+ }, []);
243
257
  const handleSelect = (0, $bvJLP$useCallback)((nodes)=>{
244
258
  if (!clickedRef.current) return;
245
259
  clickedRef.current = false;
246
- console.log("Clicked nodes:", nodes);
260
+ const isMultiSelect = ctrlPressedRef.current;
247
261
  let ids = nodes.map((d)=>parseInt(d.id));
248
- if (ids.length === 1 && ids[0] === selectedNodes[0]) ids = [];
249
- dispatch({
250
- type: "select-node",
262
+ if (isMultiSelect) dispatch({
263
+ type: "toggle-node-selected",
251
264
  payload: {
252
265
  ids: ids
253
266
  }
254
267
  });
268
+ else {
269
+ if (ids.length === 1 && ids[0] === selectedNodes[0]) ids = [];
270
+ dispatch({
271
+ type: "select-node",
272
+ payload: {
273
+ ids: ids
274
+ }
275
+ });
276
+ }
255
277
  }, [
256
278
  selectedNodes,
257
279
  dispatch
@@ -442,8 +464,12 @@ function $71d20dff35996763$var$TypeOverlay({ setOverlayOpen: setOverlayOpen, ove
442
464
  }
443
465
  function $71d20dff35996763$var$TypeTag({ type: type, luminance: luminance, selectedType: selectedType, setSelectedType: setSelectedType, dispatch: dispatch, tree: tree, selectedNodes: selectedNodes, selected: selected, isSelectedNodes: isSelectedNodes }) {
444
466
  const { color: color, name: name, id: id, description: description } = type;
445
- const chromaColor = (0, $bvJLP$asChromaColor)(color ?? "#000000");
446
467
  const darkMode = (0, $bvJLP$useInDarkMode)();
468
+ const isSelected = id === selected?.id && selectedNodes.length > 0;
469
+ const style = (0, $03d8811e9c9b360d$export$35baa338324d8550)(color, {
470
+ active: isSelected,
471
+ highlighted: selectedNodes.length === 0
472
+ });
447
473
  const payload = {
448
474
  id: id,
449
475
  name: name,
@@ -515,9 +541,9 @@ function $71d20dff35996763$var$TypeTag({ type: type, luminance: luminance, selec
515
541
  onClick: handleTagClick,
516
542
  style: {
517
543
  cursor: ids.length > 0 || isSelectedNodes && !selectedType ? "pointer" : "",
518
- color: darkMode ? "white" : "black",
519
- backgroundColor: chromaColor?.luminance(1 - luminance).hex(),
520
- border: id === selected?.id && selectedNodes.length > 0 ? `1px solid var(--text-emphasized-color)` : `1px solid var(--background-color)`
544
+ color: "black",
545
+ backgroundColor: style.backgroundColor,
546
+ border: isSelected ? `1px solid var(--text-emphasized-color)` : `1px solid var(--background-color)`
521
547
  }
522
548
  }, $71d20dff35996763$var$h("div.type-container", [
523
549
  $71d20dff35996763$var$h("div.type-name", name),
@@ -549,4 +575,4 @@ function $71d20dff35996763$var$TypeTag({ type: type, luminance: luminance, selec
549
575
 
550
576
 
551
577
  export {$71d20dff35996763$export$a90600c9da52b40c as FeedbackComponent, $b79bf29960412ca7$export$8d9dbb7a64bf2a5e as treeToGraph};
552
- //# sourceMappingURL=feedback-components.6a6c8af5.js.map
578
+ //# sourceMappingURL=feedback-components.586103e8.js.map