@macrostrat/feedback-components 1.1.3 → 1.1.5

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 (69) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/esm/feedback-components.03f08dc7.js +287 -0
  3. package/dist/esm/feedback-components.03f08dc7.js.map +1 -0
  4. package/dist/esm/feedback-components.06a79c6a.js +354 -0
  5. package/dist/esm/feedback-components.06a79c6a.js.map +1 -0
  6. package/dist/esm/{feedback-components.f577ebea.js → feedback-components.3f59f2a5.js} +14 -89
  7. package/dist/esm/feedback-components.3f59f2a5.js.map +1 -0
  8. package/dist/esm/{feedback-components.45d25912.js → feedback-components.4cbd249a.js} +5 -5
  9. package/dist/esm/{feedback-components.45d25912.js.map → feedback-components.4cbd249a.js.map} +1 -1
  10. package/dist/esm/{feedback-components.fb60c70d.css → feedback-components.5a8f0185.css} +29 -4
  11. package/dist/esm/feedback-components.5a8f0185.css.map +1 -0
  12. package/dist/esm/{feedback-components.fa1d3641.js → feedback-components.6cec1102.js} +84 -9
  13. package/dist/esm/feedback-components.6cec1102.js.map +1 -0
  14. package/dist/esm/{feedback-components.95dbe7d7.js → feedback-components.7c2fe400.js} +16 -1
  15. package/dist/esm/feedback-components.7c2fe400.js.map +1 -0
  16. package/dist/esm/{feedback-components.832b2eae.js → feedback-components.939a3a9f.js} +7 -7
  17. package/dist/esm/feedback-components.939a3a9f.js.map +1 -0
  18. package/dist/esm/feedback-components.e53837d9.js +248 -0
  19. package/dist/esm/feedback-components.e53837d9.js.map +1 -0
  20. package/dist/esm/index.d.ts +2 -1
  21. package/dist/esm/index.d.ts.map +1 -1
  22. package/dist/esm/index.js +1 -1
  23. package/dist/node/{feedback-components.f9abf0d6.js → feedback-components.3888aa2a.js} +2 -2
  24. package/dist/node/{feedback-components.f9abf0d6.js.map → feedback-components.3888aa2a.js.map} +1 -1
  25. package/dist/node/feedback-components.388de4ac.js +2 -0
  26. package/dist/node/feedback-components.388de4ac.js.map +1 -0
  27. package/dist/node/feedback-components.827f8d80.js +2 -0
  28. package/dist/node/feedback-components.827f8d80.js.map +1 -0
  29. package/dist/node/feedback-components.9e1d4e4c.js +2 -0
  30. package/dist/node/feedback-components.9e1d4e4c.js.map +1 -0
  31. package/dist/node/feedback-components.b8da3bce.js +2 -0
  32. package/dist/node/feedback-components.b8da3bce.js.map +1 -0
  33. package/dist/node/feedback-components.c31cf831.js +2 -0
  34. package/dist/node/feedback-components.c31cf831.js.map +1 -0
  35. package/dist/node/feedback-components.db4d0a14.css +2 -0
  36. package/dist/node/feedback-components.db4d0a14.css.map +1 -0
  37. package/dist/node/feedback-components.f91331e9.js +2 -0
  38. package/dist/node/feedback-components.f91331e9.js.map +1 -0
  39. package/dist/node/feedback-components.fc0395df.js +2 -0
  40. package/dist/node/feedback-components.fc0395df.js.map +1 -0
  41. package/dist/node/index.js +1 -1
  42. package/dist/node/index.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/feedback/edit-state.ts +99 -3
  45. package/src/feedback/feedback.module.sass +24 -4
  46. package/src/feedback/graph.ts +5 -2
  47. package/src/feedback/index.ts +39 -320
  48. package/src/feedback/matches.ts +279 -0
  49. package/src/feedback/text-visualizer.ts +34 -88
  50. package/src/feedback/typelist.ts +321 -0
  51. package/dist/esm/feedback-components.1e7da538.js +0 -587
  52. package/dist/esm/feedback-components.1e7da538.js.map +0 -1
  53. package/dist/esm/feedback-components.832b2eae.js.map +0 -1
  54. package/dist/esm/feedback-components.95dbe7d7.js.map +0 -1
  55. package/dist/esm/feedback-components.f577ebea.js.map +0 -1
  56. package/dist/esm/feedback-components.fa1d3641.js.map +0 -1
  57. package/dist/esm/feedback-components.fb60c70d.css.map +0 -1
  58. package/dist/node/feedback-components.25f1909a.js +0 -2
  59. package/dist/node/feedback-components.25f1909a.js.map +0 -1
  60. package/dist/node/feedback-components.4cd6b208.js +0 -2
  61. package/dist/node/feedback-components.4cd6b208.js.map +0 -1
  62. package/dist/node/feedback-components.9328e8ba.js +0 -2
  63. package/dist/node/feedback-components.9328e8ba.js.map +0 -1
  64. package/dist/node/feedback-components.b7946db4.js +0 -2
  65. package/dist/node/feedback-components.b7946db4.js.map +0 -1
  66. package/dist/node/feedback-components.c459cc27.js +0 -2
  67. package/dist/node/feedback-components.c459cc27.js.map +0 -1
  68. package/dist/node/feedback-components.c88cb37f.css +0 -2
  69. package/dist/node/feedback-components.c88cb37f.css.map +0 -1
@@ -0,0 +1,321 @@
1
+ import styles from "./feedback.module.sass";
2
+ import hyper from "@macrostrat/hyper";
3
+
4
+ import { getTagStyle } from "../extractions";
5
+ import { useState } from "react";
6
+ import { Icon, Popover, Overlay2 } from "@blueprintjs/core";
7
+ import { SaveButton } from "@macrostrat/ui-components";
8
+ import { useInDarkMode } from "@macrostrat/ui-components";
9
+ import { ColorPicker } from "@macrostrat/data-sheet";
10
+
11
+ const h = hyper.styled(styles);
12
+
13
+ export function TypeList({
14
+ types,
15
+ selected,
16
+ dispatch,
17
+ selectedNodes,
18
+ tree,
19
+ viewOnly,
20
+ }) {
21
+ const [selectedType, setSelectedType] = useState(null);
22
+ const isSelectedNodes = selectedNodes.length > 0;
23
+ const darkMode = useInDarkMode();
24
+ const luminance = darkMode ? 0.9 : 0.4;
25
+
26
+ return h("div.type-list-container", [
27
+ h(
28
+ "div.type-list-header",
29
+ isSelectedNodes && !selectedType
30
+ ? "Change selected nodes to:"
31
+ : "Entity Types",
32
+ ),
33
+ h(
34
+ "div.type-list",
35
+ Array.from(types.values()).map((type) =>
36
+ h(TypeTag, {
37
+ type,
38
+ luminance,
39
+ selectedType,
40
+ setSelectedType,
41
+ dispatch,
42
+ viewOnly,
43
+ tree,
44
+ selectedNodes,
45
+ selected,
46
+ isSelectedNodes,
47
+ }),
48
+ ),
49
+ ),
50
+ h.if(!viewOnly)(AddType, { dispatch }),
51
+ ]);
52
+ }
53
+
54
+ function collectMatchingIds(tree, id) {
55
+ const ids = [];
56
+
57
+ function traverse(node) {
58
+ if (node.type.id === id) {
59
+ ids.push(node.id);
60
+ }
61
+ if (Array.isArray(node.children)) {
62
+ node.children.forEach(traverse);
63
+ }
64
+ }
65
+
66
+ tree.forEach(traverse);
67
+ return ids;
68
+ }
69
+
70
+ function AddType({ dispatch }) {
71
+ const [overlayOpen, setOverlayOpen] = useState(false);
72
+
73
+ const saveHandler = (payload) => {
74
+ dispatch({
75
+ type: "add-entity-type",
76
+ payload,
77
+ });
78
+ setOverlayOpen(false);
79
+ };
80
+
81
+ return h("div.add-type-container", [
82
+ h("div.add-type", { onClick: () => setOverlayOpen(true) }, [
83
+ h("p.add-type-text", "Add new type"),
84
+ h(Icon, { icon: "plus" }),
85
+ ]),
86
+ h(TypeOverlay, {
87
+ setOverlayOpen,
88
+ overlayOpen,
89
+ title: "Add New Type",
90
+ saveHandler,
91
+ }),
92
+ ]);
93
+ }
94
+
95
+ function EditType({ dispatch, type }) {
96
+ const [editorOpen, setEditorOpen] = useState(false);
97
+
98
+ const saveHandler = (payload) => {
99
+ dispatch({
100
+ type: "update-entity-type",
101
+ payload,
102
+ });
103
+ setEditorOpen(false);
104
+ };
105
+
106
+ return h("div.edit-type", [
107
+ h(Icon, {
108
+ icon: "edit",
109
+ className: "edit-icon",
110
+ onClick: (e) => {
111
+ e.stopPropagation();
112
+ setEditorOpen(true);
113
+ },
114
+ }),
115
+ h(TypeOverlay, {
116
+ setOverlayOpen: setEditorOpen,
117
+ overlayOpen: editorOpen,
118
+ originalType: type,
119
+ title: "Edit Type",
120
+ saveHandler,
121
+ }),
122
+ ]);
123
+ }
124
+
125
+ function TypeOverlay({
126
+ setOverlayOpen,
127
+ overlayOpen,
128
+ originalType,
129
+ title,
130
+ saveHandler,
131
+ }) {
132
+ const { name, description, color, id } = originalType || {};
133
+
134
+ const [nameInput, setNameInput] = useState(name || "");
135
+ const [descriptionInput, setDescriptionInput] = useState(description || "");
136
+ const [colorInput, setColorInput] = useState(color || "#fff");
137
+
138
+ return h(
139
+ Overlay2,
140
+ {
141
+ isOpen: overlayOpen,
142
+ },
143
+ h(
144
+ "div.overlay-container",
145
+ h("div.add-type-overlay", [
146
+ h("h2.title", [
147
+ title,
148
+ h(Icon, {
149
+ icon: "cross",
150
+ className: "close-icon",
151
+ onClick: () => {
152
+ setOverlayOpen(false);
153
+ },
154
+ style: { cursor: "pointer", color: "red" },
155
+ }),
156
+ ]),
157
+ h("div.form-group", [
158
+ h("div.text-inputs", [
159
+ h("div.form-field.name", [
160
+ h("p.label", "Name"),
161
+ h("input", {
162
+ type: "text",
163
+ placeholder: "Enter type name",
164
+ onChange: (e) => setNameInput(e.target.value),
165
+ value: nameInput,
166
+ }),
167
+ ]),
168
+ h("div.form-field.form-description", [
169
+ h("p.label", "Description"),
170
+ h("input", {
171
+ type: "text",
172
+ placeholder: "Enter type description",
173
+ onChange: (e) => setDescriptionInput(e.target.value),
174
+ value: descriptionInput,
175
+ }),
176
+ ]),
177
+ ]),
178
+ h("div.form-field.color", [
179
+ h("p.label", "Color"),
180
+ h(ColorPicker, {
181
+ value: colorInput,
182
+ onChange: (color) => setColorInput(color),
183
+ style: { width: "100%" },
184
+ }),
185
+ ]),
186
+ ]),
187
+ h(
188
+ SaveButton,
189
+ {
190
+ className: "save-btn",
191
+ small: true,
192
+ onClick: () =>
193
+ saveHandler({
194
+ name: nameInput,
195
+ description: descriptionInput,
196
+ color: colorInput,
197
+ id,
198
+ }),
199
+ },
200
+ "Save changes",
201
+ ),
202
+ ]),
203
+ ),
204
+ );
205
+ }
206
+
207
+ function TypeTag({
208
+ type,
209
+ luminance,
210
+ selectedType,
211
+ setSelectedType,
212
+ dispatch,
213
+ tree,
214
+ selectedNodes,
215
+ selected,
216
+ isSelectedNodes,
217
+ viewOnly,
218
+ }) {
219
+ const { color, name, id, description } = type;
220
+ const darkMode = useInDarkMode();
221
+ const isSelected = id === selected?.id && selectedNodes.length > 0;
222
+
223
+ const style = getTagStyle(color, {
224
+ active: isSelected,
225
+ highlighted: selectedNodes.length === 0,
226
+ });
227
+
228
+ const payload = {
229
+ id,
230
+ name,
231
+ color,
232
+ description,
233
+ };
234
+
235
+ const ids = collectMatchingIds(tree, id);
236
+
237
+ const handleTagClick = () => {
238
+ if (!isSelectedNodes && selectedType === null) {
239
+ if (ids.length > 0) {
240
+ setSelectedType(type);
241
+ dispatch({ type: "toggle-node-selected", payload: { ids } });
242
+ }
243
+ } else if (isSelectedNodes && selectedType === null) {
244
+ if (id === selected?.id && selectedNodes.length > 0) {
245
+ dispatch({
246
+ type: "toggle-node-selected",
247
+ payload: { ids: selectedNodes },
248
+ });
249
+ } else {
250
+ dispatch({ type: "select-entity-type", payload });
251
+ }
252
+ } else if (isSelectedNodes && selectedType.id === id) {
253
+ setSelectedType(null);
254
+ dispatch({ type: "toggle-node-selected", payload: { ids } });
255
+ } else if (isSelectedNodes && selectedType.id !== id) {
256
+ if (ids.length > 0) {
257
+ setSelectedType(type);
258
+ const oldIds = collectMatchingIds(tree, selectedType.id);
259
+
260
+ dispatch({ type: "toggle-node-selected", payload: { ids: oldIds } });
261
+ dispatch({ type: "toggle-node-selected", payload: { ids } });
262
+ }
263
+ } else {
264
+ console.warn("Unexpected state in TypeTag click handler", {
265
+ isSelectedNodes,
266
+ selectedType,
267
+ selectedNodes,
268
+ ids,
269
+ id,
270
+ selected,
271
+ });
272
+ }
273
+ };
274
+
275
+ return h(
276
+ Popover,
277
+ {
278
+ autoFocus: false,
279
+ content: h("div.description", description || "No description available"),
280
+ interactionKind: "hover",
281
+ },
282
+ h(
283
+ "div.type-tag",
284
+ {
285
+ onClick: handleTagClick,
286
+ style: {
287
+ cursor:
288
+ (ids.length > 0 || (isSelectedNodes && !selectedType)) && !viewOnly
289
+ ? "pointer"
290
+ : "",
291
+ color: "black",
292
+ backgroundColor: style.backgroundColor,
293
+ border: isSelected
294
+ ? `1px solid var(--text-emphasized-color)`
295
+ : `1px solid var(--background-color)`,
296
+ },
297
+ },
298
+ h("div.type-container", [
299
+ h("div.type-name", name),
300
+ h.if(!viewOnly)("div.icons", [
301
+ h(EditType, {
302
+ dispatch,
303
+ type,
304
+ }),
305
+ h(Icon, {
306
+ icon: "cross",
307
+ className: "delete-type-icon",
308
+ style: { color: "red", cursor: "pointer" },
309
+ onClick: (e) => {
310
+ e.stopPropagation();
311
+ dispatch({
312
+ type: "delete-entity-type",
313
+ payload: { id },
314
+ });
315
+ },
316
+ }),
317
+ ]),
318
+ ]),
319
+ ),
320
+ );
321
+ }