@macrostrat/feedback-components 1.1.10 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/extractions/index.cjs +198 -0
- package/dist/extractions/index.cjs.map +1 -0
- package/dist/extractions/index.d.ts +30 -0
- package/dist/extractions/index.js +198 -0
- package/dist/extractions/index.js.map +1 -0
- package/dist/extractions/main.module.sass.cjs +12 -0
- package/dist/extractions/main.module.sass.cjs.map +1 -0
- package/dist/extractions/main.module.sass.js +12 -0
- package/dist/extractions/main.module.sass.js.map +1 -0
- package/dist/extractions/types.d.ts +32 -0
- package/dist/feedback/edit-state.cjs +382 -0
- package/dist/feedback/edit-state.cjs.map +1 -0
- package/dist/feedback/edit-state.d.ts +127 -0
- package/dist/feedback/edit-state.js +382 -0
- package/dist/feedback/edit-state.js.map +1 -0
- package/dist/feedback/feedback.module.sass.cjs +47 -0
- package/dist/feedback/feedback.module.sass.cjs.map +1 -0
- package/dist/feedback/feedback.module.sass.js +47 -0
- package/dist/feedback/feedback.module.sass.js.map +1 -0
- package/dist/feedback/graph.cjs +124 -0
- package/dist/feedback/graph.cjs.map +1 -0
- package/dist/feedback/graph.d.ts +9 -0
- package/dist/feedback/graph.js +124 -0
- package/dist/feedback/graph.js.map +1 -0
- package/dist/feedback/index.cjs +347 -0
- package/dist/feedback/index.cjs.map +1 -0
- package/dist/feedback/index.d.ts +15 -0
- package/dist/feedback/index.js +348 -0
- package/dist/feedback/index.js.map +1 -0
- package/dist/feedback/matches.cjs +244 -0
- package/dist/feedback/matches.cjs.map +1 -0
- package/dist/feedback/matches.d.ts +17 -0
- package/dist/feedback/matches.js +244 -0
- package/dist/feedback/matches.js.map +1 -0
- package/dist/feedback/node.cjs +63 -0
- package/dist/feedback/node.cjs.map +1 -0
- package/dist/feedback/node.d.ts +5 -0
- package/dist/feedback/node.js +63 -0
- package/dist/feedback/node.js.map +1 -0
- package/dist/feedback/text-visualizer.cjs +288 -0
- package/dist/feedback/text-visualizer.cjs.map +1 -0
- package/dist/feedback/text-visualizer.d.ts +36 -0
- package/dist/feedback/text-visualizer.js +288 -0
- package/dist/feedback/text-visualizer.js.map +1 -0
- package/dist/feedback/type-selector/index.cjs +47 -0
- package/dist/feedback/type-selector/index.cjs.map +1 -0
- package/dist/feedback/type-selector/index.d.ts +20 -0
- package/dist/feedback/type-selector/index.js +47 -0
- package/dist/feedback/type-selector/index.js.map +1 -0
- package/dist/feedback/type-selector/main.module.sass.cjs +13 -0
- package/dist/feedback/type-selector/main.module.sass.cjs.map +1 -0
- package/dist/feedback/type-selector/main.module.sass.js +13 -0
- package/dist/feedback/type-selector/main.module.sass.js.map +1 -0
- package/dist/feedback/typelist.cjs +293 -0
- package/dist/feedback/typelist.cjs.map +1 -0
- package/dist/feedback/typelist.d.ts +8 -0
- package/dist/feedback/typelist.js +293 -0
- package/dist/feedback/typelist.js.map +1 -0
- package/dist/feedback/types.d.ts +64 -0
- package/dist/feedback-components.css +343 -0
- package/dist/index.cjs +14 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -41
- package/src/extractions/index.ts +2 -2
- package/src/feedback/text-visualizer.ts +0 -1
- package/src/feedback/types.ts +2 -2
- package/dist/esm/feedback-components.2364179b.js +0 -287
- package/dist/esm/feedback-components.2364179b.js.map +0 -1
- package/dist/esm/feedback-components.6d32ee91.js +0 -16
- package/dist/esm/feedback-components.6d32ee91.js.map +0 -1
- package/dist/esm/feedback-components.7dd42a9f.js +0 -248
- package/dist/esm/feedback-components.7dd42a9f.js.map +0 -1
- package/dist/esm/feedback-components.7f72e5e9.js +0 -64
- package/dist/esm/feedback-components.7f72e5e9.js.map +0 -1
- package/dist/esm/feedback-components.ad9f284e.js +0 -63
- package/dist/esm/feedback-components.ad9f284e.js.map +0 -1
- package/dist/esm/feedback-components.ba79c0ef.js +0 -204
- package/dist/esm/feedback-components.ba79c0ef.js.map +0 -1
- package/dist/esm/feedback-components.bf93773c.css +0 -17
- package/dist/esm/feedback-components.bf93773c.css.map +0 -1
- package/dist/esm/feedback-components.c6e2c296.js +0 -148
- package/dist/esm/feedback-components.c6e2c296.js.map +0 -1
- package/dist/esm/feedback-components.ca78c2d4.js +0 -287
- package/dist/esm/feedback-components.ca78c2d4.js.map +0 -1
- package/dist/esm/feedback-components.d769ffa5.css +0 -205
- package/dist/esm/feedback-components.d769ffa5.css.map +0 -1
- package/dist/esm/feedback-components.e273ed5b.css +0 -14
- package/dist/esm/feedback-components.e273ed5b.css.map +0 -1
- package/dist/esm/feedback-components.e702eece.js +0 -97
- package/dist/esm/feedback-components.e702eece.js.map +0 -1
- package/dist/esm/feedback-components.edc606bb.js +0 -360
- package/dist/esm/feedback-components.edc606bb.js.map +0 -1
- package/dist/esm/feedback-components.f9850d85.js +0 -19
- package/dist/esm/feedback-components.f9850d85.js.map +0 -1
- package/dist/esm/feedback-components.fa847634.js +0 -453
- package/dist/esm/feedback-components.fa847634.js.map +0 -1
- package/dist/esm/index.d.ts +0 -96
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/index.js +0 -9
- package/dist/esm/index.js.map +0 -1
- package/dist/node/feedback-components.1bd49bf0.js +0 -2
- package/dist/node/feedback-components.1bd49bf0.js.map +0 -1
- package/dist/node/feedback-components.2f391fa4.js +0 -2
- package/dist/node/feedback-components.2f391fa4.js.map +0 -1
- package/dist/node/feedback-components.6a4a1290.js +0 -2
- package/dist/node/feedback-components.6a4a1290.js.map +0 -1
- package/dist/node/feedback-components.70780da4.js +0 -2
- package/dist/node/feedback-components.70780da4.js.map +0 -1
- package/dist/node/feedback-components.794f429b.js +0 -2
- package/dist/node/feedback-components.794f429b.js.map +0 -1
- package/dist/node/feedback-components.83c21466.css +0 -2
- package/dist/node/feedback-components.83c21466.css.map +0 -1
- package/dist/node/feedback-components.97518e90.css +0 -2
- package/dist/node/feedback-components.97518e90.css.map +0 -1
- package/dist/node/feedback-components.9eb1d41a.css +0 -2
- package/dist/node/feedback-components.9eb1d41a.css.map +0 -1
- package/dist/node/feedback-components.acac789b.js +0 -2
- package/dist/node/feedback-components.acac789b.js.map +0 -1
- package/dist/node/feedback-components.c84ff10e.js +0 -2
- package/dist/node/feedback-components.c84ff10e.js.map +0 -1
- package/dist/node/feedback-components.db72d0e1.js +0 -2
- package/dist/node/feedback-components.db72d0e1.js.map +0 -1
- package/dist/node/feedback-components.dc76072c.js +0 -2
- package/dist/node/feedback-components.dc76072c.js.map +0 -1
- package/dist/node/feedback-components.ddd11fe8.js +0 -2
- package/dist/node/feedback-components.ddd11fe8.js.map +0 -1
- package/dist/node/feedback-components.e59a061f.js +0 -2
- package/dist/node/feedback-components.e59a061f.js.map +0 -1
- package/dist/node/feedback-components.feab0bd0.js +0 -2
- package/dist/node/feedback-components.feab0bd0.js.map +0 -1
- package/dist/node/index.js +0 -2
- package/dist/node/index.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
|
+
## [2.0.0] - 2026-01-26
|
|
8
|
+
|
|
9
|
+
- Update peer dependencies to React 18
|
|
10
|
+
- Update bundling process to `@macrostrat/web-components-bundler`
|
|
11
|
+
- Import of `@macrostrat/feedback-components/styles.css` is now required.
|
|
12
|
+
|
|
7
13
|
## [1.1.10] - 2025-11-28
|
|
8
14
|
|
|
9
15
|
- Upgrade `parcel` bundler
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const main_module = require("./main.module.sass.cjs");
|
|
4
|
+
const classNames = require("classnames");
|
|
5
|
+
const core = require("@blueprintjs/core");
|
|
6
|
+
const colorUtils = require("@macrostrat/color-utils");
|
|
7
|
+
const hyper = require("@macrostrat/hyper");
|
|
8
|
+
const uiComponents = require("@macrostrat/ui-components");
|
|
9
|
+
const h = hyper.styled(main_module.default);
|
|
10
|
+
function buildHighlights(entities, parent) {
|
|
11
|
+
let highlights = [];
|
|
12
|
+
let parents = [];
|
|
13
|
+
if (parent != null) {
|
|
14
|
+
parents = [parent.id, ...parent.parents ?? []];
|
|
15
|
+
}
|
|
16
|
+
for (const entity of entities) {
|
|
17
|
+
highlights.push({
|
|
18
|
+
start: entity.indices[0],
|
|
19
|
+
end: entity.indices[1],
|
|
20
|
+
text: entity.name,
|
|
21
|
+
backgroundColor: entity.type?.color,
|
|
22
|
+
tag: entity.type?.name ?? "lith",
|
|
23
|
+
id: entity.id,
|
|
24
|
+
parents,
|
|
25
|
+
match: entity.match
|
|
26
|
+
});
|
|
27
|
+
highlights.push(...buildHighlights(entity.children ?? [], entity));
|
|
28
|
+
}
|
|
29
|
+
return highlights;
|
|
30
|
+
}
|
|
31
|
+
function enhanceData(extractionData, models, entityTypes) {
|
|
32
|
+
return {
|
|
33
|
+
...extractionData,
|
|
34
|
+
model: models.get(extractionData.model_id),
|
|
35
|
+
entities: extractionData.entities?.map(
|
|
36
|
+
(d) => enhanceEntity(d, entityTypes)
|
|
37
|
+
)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function getTagStyle(baseColor, options = {}) {
|
|
41
|
+
const _baseColor = colorUtils.asChromaColor(baseColor ?? "#fff");
|
|
42
|
+
const {
|
|
43
|
+
highlighted = true,
|
|
44
|
+
inDarkMode = uiComponents.useDarkMode().isEnabled,
|
|
45
|
+
active = false
|
|
46
|
+
} = options;
|
|
47
|
+
let mixAmount = highlighted ? 0.8 : 0.5;
|
|
48
|
+
let backgroundAlpha = highlighted ? 0.8 : 0.2;
|
|
49
|
+
if (active) {
|
|
50
|
+
mixAmount = 1;
|
|
51
|
+
backgroundAlpha = 1;
|
|
52
|
+
}
|
|
53
|
+
const mixTarget = "black";
|
|
54
|
+
const color = active ? "#000" : _baseColor.mix(mixTarget, mixAmount).hex();
|
|
55
|
+
const borderColor = highlighted ? _baseColor.mix(mixTarget, mixAmount / 1.1).hex() : "transparent";
|
|
56
|
+
let backgroundColor = active ? _baseColor.alpha(backgroundAlpha).hex() : normalizeColor(_baseColor.alpha(backgroundAlpha).hex());
|
|
57
|
+
if (!inDarkMode && backgroundColor === "#ffffff") {
|
|
58
|
+
backgroundColor = "#f0f0f0";
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
color,
|
|
62
|
+
backgroundColor,
|
|
63
|
+
boxSizing: "border-box",
|
|
64
|
+
borderStyle: "solid",
|
|
65
|
+
borderColor,
|
|
66
|
+
borderWidth: "1.5px",
|
|
67
|
+
fontWeight: active ? "bold" : "normal",
|
|
68
|
+
fontSize: "0.9em"
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function enhanceEntity(entity, entityTypes) {
|
|
72
|
+
return {
|
|
73
|
+
...entity,
|
|
74
|
+
type: addColor(entityTypes.get(entity.type), entity.match != null),
|
|
75
|
+
children: entity.children?.map((d) => enhanceEntity(d, entityTypes))
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function addColor(entityType, match = false) {
|
|
79
|
+
const color = colorUtils.asChromaColor(entityType.color ?? "#fff").brighten(
|
|
80
|
+
match ? 1 : 2
|
|
81
|
+
);
|
|
82
|
+
return { ...entityType, color: color.css() };
|
|
83
|
+
}
|
|
84
|
+
function ExtractionContext({
|
|
85
|
+
data,
|
|
86
|
+
entityTypes,
|
|
87
|
+
matchComponent
|
|
88
|
+
}) {
|
|
89
|
+
const highlights = buildHighlights(data.entities, null);
|
|
90
|
+
return h("div", [
|
|
91
|
+
h("p", h(HighlightedText, { text: data.paragraph_text, highlights })),
|
|
92
|
+
h(ModelInfo, { data: data.model }),
|
|
93
|
+
h(
|
|
94
|
+
"ul.entities",
|
|
95
|
+
data.entities.map((d) => h(ExtractionInfo, { data: d, matchComponent }))
|
|
96
|
+
)
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
function ModelInfo({ data }) {
|
|
100
|
+
if (!data) return null;
|
|
101
|
+
return h("p.model-name", ["Model: ", h("code.bp6-code", data.name)]);
|
|
102
|
+
}
|
|
103
|
+
function EntityTag({
|
|
104
|
+
data,
|
|
105
|
+
highlighted = true,
|
|
106
|
+
active = false,
|
|
107
|
+
onClickType,
|
|
108
|
+
matchComponent = null
|
|
109
|
+
}) {
|
|
110
|
+
const { name, type, match } = data;
|
|
111
|
+
const className = classNames(
|
|
112
|
+
{
|
|
113
|
+
matched: match != null,
|
|
114
|
+
type: data.type?.name ?? "lith"
|
|
115
|
+
},
|
|
116
|
+
"entity"
|
|
117
|
+
);
|
|
118
|
+
const style = getTagStyle(type?.color, { highlighted, active });
|
|
119
|
+
let _matchLink = null;
|
|
120
|
+
if (match != null && matchComponent != null) {
|
|
121
|
+
_matchLink = h(matchComponent, { data: match });
|
|
122
|
+
}
|
|
123
|
+
return h(core.Tag, { style, className }, [
|
|
124
|
+
h("span.entity-name", name),
|
|
125
|
+
" ",
|
|
126
|
+
h(
|
|
127
|
+
"code.entity-type.bp6-code",
|
|
128
|
+
{
|
|
129
|
+
onClick(evt) {
|
|
130
|
+
if (active && onClickType != null) {
|
|
131
|
+
onClickType(type);
|
|
132
|
+
evt.stopPropagation();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
[type?.name, _matchLink]
|
|
137
|
+
)
|
|
138
|
+
]);
|
|
139
|
+
}
|
|
140
|
+
function ExtractionInfo({
|
|
141
|
+
data,
|
|
142
|
+
matchComponent = null
|
|
143
|
+
}) {
|
|
144
|
+
const children = data.children ?? [];
|
|
145
|
+
return h("li.entity-row", [
|
|
146
|
+
h(EntityTag, { data, matchComponent }),
|
|
147
|
+
h.if(children.length > 0)([
|
|
148
|
+
h(
|
|
149
|
+
"ul.children",
|
|
150
|
+
children.map((d) => h(ExtractionInfo, { data: d, matchComponent }))
|
|
151
|
+
)
|
|
152
|
+
])
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
function HighlightedText(props) {
|
|
156
|
+
const { text, highlights = [] } = props;
|
|
157
|
+
const parts = [];
|
|
158
|
+
let start = 0;
|
|
159
|
+
const sortedHighlights = highlights.sort((a, b) => a.start - b.start);
|
|
160
|
+
const deconflictedHighlights = sortedHighlights.map((highlight, i) => {
|
|
161
|
+
if (i === 0) return highlight;
|
|
162
|
+
const prev = sortedHighlights[i - 1];
|
|
163
|
+
if (highlight.start < prev.end) {
|
|
164
|
+
highlight.start = prev.end;
|
|
165
|
+
}
|
|
166
|
+
return highlight;
|
|
167
|
+
});
|
|
168
|
+
for (const highlight of deconflictedHighlights) {
|
|
169
|
+
const { start: s, end, ...rest } = highlight;
|
|
170
|
+
parts.push(text.slice(start, s));
|
|
171
|
+
parts.push(h("span.highlight", { style: rest }, text.slice(s, end)));
|
|
172
|
+
start = end;
|
|
173
|
+
}
|
|
174
|
+
parts.push(text.slice(start));
|
|
175
|
+
return h("span", parts);
|
|
176
|
+
}
|
|
177
|
+
function normalizeColor(hex8) {
|
|
178
|
+
const background = uiComponents.useDarkMode().isEnabled ? "#000000" : "#ffffff";
|
|
179
|
+
const r = parseInt(hex8.slice(1, 3), 16);
|
|
180
|
+
const g = parseInt(hex8.slice(3, 5), 16);
|
|
181
|
+
const b = parseInt(hex8.slice(5, 7), 16);
|
|
182
|
+
const a = parseInt(hex8.slice(7, 9), 16) / 255;
|
|
183
|
+
const bgR = parseInt(background.slice(1, 3), 16);
|
|
184
|
+
const bgG = parseInt(background.slice(3, 5), 16);
|
|
185
|
+
const bgB = parseInt(background.slice(5, 7), 16);
|
|
186
|
+
const blend = (fg, bg) => Math.round((1 - a) * bg + a * fg);
|
|
187
|
+
const blendedR = blend(r, bgR);
|
|
188
|
+
const blendedG = blend(g, bgG);
|
|
189
|
+
const blendedB = blend(b, bgB);
|
|
190
|
+
return "#" + blendedR.toString(16).padStart(2, "0") + blendedG.toString(16).padStart(2, "0") + blendedB.toString(16).padStart(2, "0");
|
|
191
|
+
}
|
|
192
|
+
exports.EntityTag = EntityTag;
|
|
193
|
+
exports.ExtractionContext = ExtractionContext;
|
|
194
|
+
exports.ModelInfo = ModelInfo;
|
|
195
|
+
exports.buildHighlights = buildHighlights;
|
|
196
|
+
exports.enhanceData = enhanceData;
|
|
197
|
+
exports.getTagStyle = getTagStyle;
|
|
198
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/extractions/index.ts"],"sourcesContent":["import styles from \"./main.module.sass\";\nimport classNames from \"classnames\";\nimport { Tag } from \"@blueprintjs/core\";\nimport type { Entity, EntityExt, Highlight, EntityType } from \"./types\";\nimport { CSSProperties } from \"react\";\nimport { asChromaColor } from \"@macrostrat/color-utils\";\nimport hyper from \"@macrostrat/hyper\";\nimport { useDarkMode } from \"@macrostrat/ui-components\";\n\nexport type { Entity, EntityExt };\n\nconst h = hyper.styled(styles);\n\nexport function buildHighlights(\n entities: EntityExt[],\n parent: EntityExt | null,\n): Highlight[] {\n let highlights = [];\n let parents = [];\n if (parent != null) {\n parents = [parent.id, ...(parent.parents ?? [])];\n }\n\n for (const entity of entities) {\n highlights.push({\n start: entity.indices[0],\n end: entity.indices[1],\n text: entity.name,\n backgroundColor: entity.type?.color,\n tag: entity.type?.name ?? \"lith\",\n id: entity.id,\n parents,\n match: entity.match,\n });\n highlights.push(...buildHighlights(entity.children ?? [], entity));\n }\n return highlights;\n}\n\nexport function enhanceData(extractionData, models, entityTypes) {\n return {\n ...extractionData,\n model: models.get(extractionData.model_id),\n entities: extractionData.entities?.map((d) =>\n enhanceEntity(d, entityTypes),\n ),\n };\n}\n\nexport function getTagStyle(\n baseColor: string,\n options: {\n highlighted?: boolean;\n inDarkMode?: boolean;\n active?: boolean;\n showMatches?: boolean;\n } = {},\n): CSSProperties {\n const _baseColor = asChromaColor(baseColor ?? \"#fff\");\n const {\n highlighted = true,\n inDarkMode = useDarkMode().isEnabled,\n active = false,\n } = options;\n\n let mixAmount = highlighted ? 0.8 : 0.5;\n let backgroundAlpha = highlighted ? 0.8 : 0.2;\n\n if (active) {\n mixAmount = 1;\n backgroundAlpha = 1;\n }\n\n const mixTarget = \"black\";\n\n const color = active ? \"#000\" : _baseColor.mix(mixTarget, mixAmount).hex();\n const borderColor = highlighted\n ? _baseColor.mix(mixTarget, mixAmount / 1.1).hex()\n : \"transparent\";\n\n let backgroundColor = active\n ? _baseColor.alpha(backgroundAlpha).hex()\n : normalizeColor(_baseColor.alpha(backgroundAlpha).hex());\n\n // handle white backgrounds in light mode\n if (!inDarkMode && backgroundColor === \"#ffffff\") {\n backgroundColor = \"#f0f0f0\";\n }\n\n return {\n color,\n backgroundColor,\n boxSizing: \"border-box\",\n borderStyle: \"solid\",\n borderColor,\n borderWidth: \"1.5px\",\n fontWeight: active ? \"bold\" : \"normal\",\n fontSize: \"0.9em\",\n };\n}\n\nfunction enhanceEntity(\n entity: Entity,\n entityTypes: Map<number, EntityType>,\n): EntityExt {\n return {\n ...entity,\n type: addColor(entityTypes.get(entity.type), entity.match != null),\n children: entity.children?.map((d) => enhanceEntity(d, entityTypes)),\n };\n}\n\nfunction addColor(entityType: EntityType, match = false) {\n const color = asChromaColor(entityType.color ?? \"#fff\").brighten(\n match ? 1 : 2,\n );\n\n return { ...entityType, color: color.css() };\n}\n\nexport function ExtractionContext({\n data,\n entityTypes,\n matchComponent,\n}: {\n data: any;\n entityTypes: Map<number, EntityType>;\n matchComponent: MatchComponent;\n}) {\n const highlights = buildHighlights(data.entities, null);\n\n return h(\"div\", [\n h(\"p\", h(HighlightedText, { text: data.paragraph_text, highlights })),\n h(ModelInfo, { data: data.model }),\n h(\n \"ul.entities\",\n data.entities.map((d) => h(ExtractionInfo, { data: d, matchComponent })),\n ),\n ]);\n}\n\nexport function ModelInfo({ data }) {\n if (!data) return null;\n return h(\"p.model-name\", [\"Model: \", h(\"code.bp6-code\", data.name)]);\n}\n\nexport type MatchComponent = (props: { data: any }) => any;\n\ntype EntityTagProps = {\n data: EntityExt;\n highlighted?: boolean;\n active?: boolean;\n onClickType?: (type: EntityType) => void;\n matchComponent?: MatchComponent;\n};\n\nexport function EntityTag({\n data,\n highlighted = true,\n active = false,\n onClickType,\n matchComponent = null,\n}: EntityTagProps) {\n const { name, type, match } = data;\n\n const className = classNames(\n {\n matched: match != null,\n type: data.type?.name ?? \"lith\",\n },\n \"entity\",\n );\n\n const style = getTagStyle(type?.color, { highlighted, active });\n\n let _matchLink = null;\n if (match != null && matchComponent != null) {\n _matchLink = h(matchComponent, { data: match });\n }\n\n return h(Tag, { style, className }, [\n h(\"span.entity-name\", name),\n \" \",\n h(\n \"code.entity-type.bp6-code\",\n {\n onClick(evt) {\n if (active && onClickType != null) {\n onClickType(type);\n evt.stopPropagation();\n }\n },\n },\n [type?.name, _matchLink],\n ),\n ]);\n}\n\nfunction ExtractionInfo({\n data,\n matchComponent = null,\n}: {\n data: EntityExt;\n matchComponent: MatchComponent;\n}) {\n const children = data.children ?? [];\n\n return h(\"li.entity-row\", [\n h(EntityTag, { data, matchComponent }),\n h.if(children.length > 0)([\n h(\n \"ul.children\",\n children.map((d) => h(ExtractionInfo, { data: d, matchComponent })),\n ),\n ]),\n ]);\n}\n\nfunction HighlightedText(props: { text: string; highlights: Highlight[] }) {\n const { text, highlights = [] } = props;\n const parts = [];\n let start = 0;\n\n const sortedHighlights = highlights.sort((a, b) => a.start - b.start);\n const deconflictedHighlights = sortedHighlights.map((highlight, i) => {\n if (i === 0) return highlight;\n const prev = sortedHighlights[i - 1];\n if (highlight.start < prev.end) {\n highlight.start = prev.end;\n }\n return highlight;\n });\n\n for (const highlight of deconflictedHighlights) {\n const { start: s, end, ...rest } = highlight;\n parts.push(text.slice(start, s));\n parts.push(h(\"span.highlight\", { style: rest }, text.slice(s, end)));\n start = end;\n }\n parts.push(text.slice(start));\n return h(\"span\", parts);\n}\n\nfunction normalizeColor(hex8) {\n const background = useDarkMode().isEnabled ? \"#000000\" : \"#ffffff\";\n\n const r = parseInt(hex8.slice(1, 3), 16);\n const g = parseInt(hex8.slice(3, 5), 16);\n const b = parseInt(hex8.slice(5, 7), 16);\n const a = parseInt(hex8.slice(7, 9), 16) / 255;\n\n const bgR = parseInt(background.slice(1, 3), 16);\n const bgG = parseInt(background.slice(3, 5), 16);\n const bgB = parseInt(background.slice(5, 7), 16);\n\n const blend = (fg, bg) => Math.round((1 - a) * bg + a * fg);\n\n const blendedR = blend(r, bgR);\n const blendedG = blend(g, bgG);\n const blendedB = blend(b, bgB);\n\n return (\n \"#\" +\n blendedR.toString(16).padStart(2, \"0\") +\n blendedG.toString(16).padStart(2, \"0\") +\n blendedB.toString(16).padStart(2, \"0\")\n );\n}\n\nfunction isHighlighted(id: number, selectedNodes: number[], nodes: any[]) {\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":["styles","asChromaColor","useDarkMode","Tag"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Entity, EntityExt, Highlight, EntityType } from './types';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
export type { Entity, EntityExt };
|
|
4
|
+
export declare function buildHighlights(entities: EntityExt[], parent: EntityExt | null): Highlight[];
|
|
5
|
+
export declare function enhanceData(extractionData: any, models: any, entityTypes: any): any;
|
|
6
|
+
export declare function getTagStyle(baseColor: string, options?: {
|
|
7
|
+
highlighted?: boolean;
|
|
8
|
+
inDarkMode?: boolean;
|
|
9
|
+
active?: boolean;
|
|
10
|
+
showMatches?: boolean;
|
|
11
|
+
}): CSSProperties;
|
|
12
|
+
export declare function ExtractionContext({ data, entityTypes, matchComponent, }: {
|
|
13
|
+
data: any;
|
|
14
|
+
entityTypes: Map<number, EntityType>;
|
|
15
|
+
matchComponent: MatchComponent;
|
|
16
|
+
}): import('react').DetailedReactHTMLElement<import('react').HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
17
|
+
export declare function ModelInfo({ data }: {
|
|
18
|
+
data: any;
|
|
19
|
+
}): import('react').DOMElement<import('react').DOMAttributes<Element>, Element>;
|
|
20
|
+
export type MatchComponent = (props: {
|
|
21
|
+
data: any;
|
|
22
|
+
}) => any;
|
|
23
|
+
type EntityTagProps = {
|
|
24
|
+
data: EntityExt;
|
|
25
|
+
highlighted?: boolean;
|
|
26
|
+
active?: boolean;
|
|
27
|
+
onClickType?: (type: EntityType) => void;
|
|
28
|
+
matchComponent?: MatchComponent;
|
|
29
|
+
};
|
|
30
|
+
export declare function EntityTag({ data, highlighted, active, onClickType, matchComponent, }: EntityTagProps): import('react').FunctionComponentElement<import('@blueprintjs/core').TagProps>;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import styles from "./main.module.sass.js";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import { Tag } from "@blueprintjs/core";
|
|
4
|
+
import { asChromaColor } from "@macrostrat/color-utils";
|
|
5
|
+
import hyper from "@macrostrat/hyper";
|
|
6
|
+
import { useDarkMode } from "@macrostrat/ui-components";
|
|
7
|
+
const h = hyper.styled(styles);
|
|
8
|
+
function buildHighlights(entities, parent) {
|
|
9
|
+
let highlights = [];
|
|
10
|
+
let parents = [];
|
|
11
|
+
if (parent != null) {
|
|
12
|
+
parents = [parent.id, ...parent.parents ?? []];
|
|
13
|
+
}
|
|
14
|
+
for (const entity of entities) {
|
|
15
|
+
highlights.push({
|
|
16
|
+
start: entity.indices[0],
|
|
17
|
+
end: entity.indices[1],
|
|
18
|
+
text: entity.name,
|
|
19
|
+
backgroundColor: entity.type?.color,
|
|
20
|
+
tag: entity.type?.name ?? "lith",
|
|
21
|
+
id: entity.id,
|
|
22
|
+
parents,
|
|
23
|
+
match: entity.match
|
|
24
|
+
});
|
|
25
|
+
highlights.push(...buildHighlights(entity.children ?? [], entity));
|
|
26
|
+
}
|
|
27
|
+
return highlights;
|
|
28
|
+
}
|
|
29
|
+
function enhanceData(extractionData, models, entityTypes) {
|
|
30
|
+
return {
|
|
31
|
+
...extractionData,
|
|
32
|
+
model: models.get(extractionData.model_id),
|
|
33
|
+
entities: extractionData.entities?.map(
|
|
34
|
+
(d) => enhanceEntity(d, entityTypes)
|
|
35
|
+
)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function getTagStyle(baseColor, options = {}) {
|
|
39
|
+
const _baseColor = asChromaColor(baseColor ?? "#fff");
|
|
40
|
+
const {
|
|
41
|
+
highlighted = true,
|
|
42
|
+
inDarkMode = useDarkMode().isEnabled,
|
|
43
|
+
active = false
|
|
44
|
+
} = options;
|
|
45
|
+
let mixAmount = highlighted ? 0.8 : 0.5;
|
|
46
|
+
let backgroundAlpha = highlighted ? 0.8 : 0.2;
|
|
47
|
+
if (active) {
|
|
48
|
+
mixAmount = 1;
|
|
49
|
+
backgroundAlpha = 1;
|
|
50
|
+
}
|
|
51
|
+
const mixTarget = "black";
|
|
52
|
+
const color = active ? "#000" : _baseColor.mix(mixTarget, mixAmount).hex();
|
|
53
|
+
const borderColor = highlighted ? _baseColor.mix(mixTarget, mixAmount / 1.1).hex() : "transparent";
|
|
54
|
+
let backgroundColor = active ? _baseColor.alpha(backgroundAlpha).hex() : normalizeColor(_baseColor.alpha(backgroundAlpha).hex());
|
|
55
|
+
if (!inDarkMode && backgroundColor === "#ffffff") {
|
|
56
|
+
backgroundColor = "#f0f0f0";
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
color,
|
|
60
|
+
backgroundColor,
|
|
61
|
+
boxSizing: "border-box",
|
|
62
|
+
borderStyle: "solid",
|
|
63
|
+
borderColor,
|
|
64
|
+
borderWidth: "1.5px",
|
|
65
|
+
fontWeight: active ? "bold" : "normal",
|
|
66
|
+
fontSize: "0.9em"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function enhanceEntity(entity, entityTypes) {
|
|
70
|
+
return {
|
|
71
|
+
...entity,
|
|
72
|
+
type: addColor(entityTypes.get(entity.type), entity.match != null),
|
|
73
|
+
children: entity.children?.map((d) => enhanceEntity(d, entityTypes))
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function addColor(entityType, match = false) {
|
|
77
|
+
const color = asChromaColor(entityType.color ?? "#fff").brighten(
|
|
78
|
+
match ? 1 : 2
|
|
79
|
+
);
|
|
80
|
+
return { ...entityType, color: color.css() };
|
|
81
|
+
}
|
|
82
|
+
function ExtractionContext({
|
|
83
|
+
data,
|
|
84
|
+
entityTypes,
|
|
85
|
+
matchComponent
|
|
86
|
+
}) {
|
|
87
|
+
const highlights = buildHighlights(data.entities, null);
|
|
88
|
+
return h("div", [
|
|
89
|
+
h("p", h(HighlightedText, { text: data.paragraph_text, highlights })),
|
|
90
|
+
h(ModelInfo, { data: data.model }),
|
|
91
|
+
h(
|
|
92
|
+
"ul.entities",
|
|
93
|
+
data.entities.map((d) => h(ExtractionInfo, { data: d, matchComponent }))
|
|
94
|
+
)
|
|
95
|
+
]);
|
|
96
|
+
}
|
|
97
|
+
function ModelInfo({ data }) {
|
|
98
|
+
if (!data) return null;
|
|
99
|
+
return h("p.model-name", ["Model: ", h("code.bp6-code", data.name)]);
|
|
100
|
+
}
|
|
101
|
+
function EntityTag({
|
|
102
|
+
data,
|
|
103
|
+
highlighted = true,
|
|
104
|
+
active = false,
|
|
105
|
+
onClickType,
|
|
106
|
+
matchComponent = null
|
|
107
|
+
}) {
|
|
108
|
+
const { name, type, match } = data;
|
|
109
|
+
const className = classNames(
|
|
110
|
+
{
|
|
111
|
+
matched: match != null,
|
|
112
|
+
type: data.type?.name ?? "lith"
|
|
113
|
+
},
|
|
114
|
+
"entity"
|
|
115
|
+
);
|
|
116
|
+
const style = getTagStyle(type?.color, { highlighted, active });
|
|
117
|
+
let _matchLink = null;
|
|
118
|
+
if (match != null && matchComponent != null) {
|
|
119
|
+
_matchLink = h(matchComponent, { data: match });
|
|
120
|
+
}
|
|
121
|
+
return h(Tag, { style, className }, [
|
|
122
|
+
h("span.entity-name", name),
|
|
123
|
+
" ",
|
|
124
|
+
h(
|
|
125
|
+
"code.entity-type.bp6-code",
|
|
126
|
+
{
|
|
127
|
+
onClick(evt) {
|
|
128
|
+
if (active && onClickType != null) {
|
|
129
|
+
onClickType(type);
|
|
130
|
+
evt.stopPropagation();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
[type?.name, _matchLink]
|
|
135
|
+
)
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
function ExtractionInfo({
|
|
139
|
+
data,
|
|
140
|
+
matchComponent = null
|
|
141
|
+
}) {
|
|
142
|
+
const children = data.children ?? [];
|
|
143
|
+
return h("li.entity-row", [
|
|
144
|
+
h(EntityTag, { data, matchComponent }),
|
|
145
|
+
h.if(children.length > 0)([
|
|
146
|
+
h(
|
|
147
|
+
"ul.children",
|
|
148
|
+
children.map((d) => h(ExtractionInfo, { data: d, matchComponent }))
|
|
149
|
+
)
|
|
150
|
+
])
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
function HighlightedText(props) {
|
|
154
|
+
const { text, highlights = [] } = props;
|
|
155
|
+
const parts = [];
|
|
156
|
+
let start = 0;
|
|
157
|
+
const sortedHighlights = highlights.sort((a, b) => a.start - b.start);
|
|
158
|
+
const deconflictedHighlights = sortedHighlights.map((highlight, i) => {
|
|
159
|
+
if (i === 0) return highlight;
|
|
160
|
+
const prev = sortedHighlights[i - 1];
|
|
161
|
+
if (highlight.start < prev.end) {
|
|
162
|
+
highlight.start = prev.end;
|
|
163
|
+
}
|
|
164
|
+
return highlight;
|
|
165
|
+
});
|
|
166
|
+
for (const highlight of deconflictedHighlights) {
|
|
167
|
+
const { start: s, end, ...rest } = highlight;
|
|
168
|
+
parts.push(text.slice(start, s));
|
|
169
|
+
parts.push(h("span.highlight", { style: rest }, text.slice(s, end)));
|
|
170
|
+
start = end;
|
|
171
|
+
}
|
|
172
|
+
parts.push(text.slice(start));
|
|
173
|
+
return h("span", parts);
|
|
174
|
+
}
|
|
175
|
+
function normalizeColor(hex8) {
|
|
176
|
+
const background = useDarkMode().isEnabled ? "#000000" : "#ffffff";
|
|
177
|
+
const r = parseInt(hex8.slice(1, 3), 16);
|
|
178
|
+
const g = parseInt(hex8.slice(3, 5), 16);
|
|
179
|
+
const b = parseInt(hex8.slice(5, 7), 16);
|
|
180
|
+
const a = parseInt(hex8.slice(7, 9), 16) / 255;
|
|
181
|
+
const bgR = parseInt(background.slice(1, 3), 16);
|
|
182
|
+
const bgG = parseInt(background.slice(3, 5), 16);
|
|
183
|
+
const bgB = parseInt(background.slice(5, 7), 16);
|
|
184
|
+
const blend = (fg, bg) => Math.round((1 - a) * bg + a * fg);
|
|
185
|
+
const blendedR = blend(r, bgR);
|
|
186
|
+
const blendedG = blend(g, bgG);
|
|
187
|
+
const blendedB = blend(b, bgB);
|
|
188
|
+
return "#" + blendedR.toString(16).padStart(2, "0") + blendedG.toString(16).padStart(2, "0") + blendedB.toString(16).padStart(2, "0");
|
|
189
|
+
}
|
|
190
|
+
export {
|
|
191
|
+
EntityTag,
|
|
192
|
+
ExtractionContext,
|
|
193
|
+
ModelInfo,
|
|
194
|
+
buildHighlights,
|
|
195
|
+
enhanceData,
|
|
196
|
+
getTagStyle
|
|
197
|
+
};
|
|
198
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/extractions/index.ts"],"sourcesContent":["import styles from \"./main.module.sass\";\nimport classNames from \"classnames\";\nimport { Tag } from \"@blueprintjs/core\";\nimport type { Entity, EntityExt, Highlight, EntityType } from \"./types\";\nimport { CSSProperties } from \"react\";\nimport { asChromaColor } from \"@macrostrat/color-utils\";\nimport hyper from \"@macrostrat/hyper\";\nimport { useDarkMode } from \"@macrostrat/ui-components\";\n\nexport type { Entity, EntityExt };\n\nconst h = hyper.styled(styles);\n\nexport function buildHighlights(\n entities: EntityExt[],\n parent: EntityExt | null,\n): Highlight[] {\n let highlights = [];\n let parents = [];\n if (parent != null) {\n parents = [parent.id, ...(parent.parents ?? [])];\n }\n\n for (const entity of entities) {\n highlights.push({\n start: entity.indices[0],\n end: entity.indices[1],\n text: entity.name,\n backgroundColor: entity.type?.color,\n tag: entity.type?.name ?? \"lith\",\n id: entity.id,\n parents,\n match: entity.match,\n });\n highlights.push(...buildHighlights(entity.children ?? [], entity));\n }\n return highlights;\n}\n\nexport function enhanceData(extractionData, models, entityTypes) {\n return {\n ...extractionData,\n model: models.get(extractionData.model_id),\n entities: extractionData.entities?.map((d) =>\n enhanceEntity(d, entityTypes),\n ),\n };\n}\n\nexport function getTagStyle(\n baseColor: string,\n options: {\n highlighted?: boolean;\n inDarkMode?: boolean;\n active?: boolean;\n showMatches?: boolean;\n } = {},\n): CSSProperties {\n const _baseColor = asChromaColor(baseColor ?? \"#fff\");\n const {\n highlighted = true,\n inDarkMode = useDarkMode().isEnabled,\n active = false,\n } = options;\n\n let mixAmount = highlighted ? 0.8 : 0.5;\n let backgroundAlpha = highlighted ? 0.8 : 0.2;\n\n if (active) {\n mixAmount = 1;\n backgroundAlpha = 1;\n }\n\n const mixTarget = \"black\";\n\n const color = active ? \"#000\" : _baseColor.mix(mixTarget, mixAmount).hex();\n const borderColor = highlighted\n ? _baseColor.mix(mixTarget, mixAmount / 1.1).hex()\n : \"transparent\";\n\n let backgroundColor = active\n ? _baseColor.alpha(backgroundAlpha).hex()\n : normalizeColor(_baseColor.alpha(backgroundAlpha).hex());\n\n // handle white backgrounds in light mode\n if (!inDarkMode && backgroundColor === \"#ffffff\") {\n backgroundColor = \"#f0f0f0\";\n }\n\n return {\n color,\n backgroundColor,\n boxSizing: \"border-box\",\n borderStyle: \"solid\",\n borderColor,\n borderWidth: \"1.5px\",\n fontWeight: active ? \"bold\" : \"normal\",\n fontSize: \"0.9em\",\n };\n}\n\nfunction enhanceEntity(\n entity: Entity,\n entityTypes: Map<number, EntityType>,\n): EntityExt {\n return {\n ...entity,\n type: addColor(entityTypes.get(entity.type), entity.match != null),\n children: entity.children?.map((d) => enhanceEntity(d, entityTypes)),\n };\n}\n\nfunction addColor(entityType: EntityType, match = false) {\n const color = asChromaColor(entityType.color ?? \"#fff\").brighten(\n match ? 1 : 2,\n );\n\n return { ...entityType, color: color.css() };\n}\n\nexport function ExtractionContext({\n data,\n entityTypes,\n matchComponent,\n}: {\n data: any;\n entityTypes: Map<number, EntityType>;\n matchComponent: MatchComponent;\n}) {\n const highlights = buildHighlights(data.entities, null);\n\n return h(\"div\", [\n h(\"p\", h(HighlightedText, { text: data.paragraph_text, highlights })),\n h(ModelInfo, { data: data.model }),\n h(\n \"ul.entities\",\n data.entities.map((d) => h(ExtractionInfo, { data: d, matchComponent })),\n ),\n ]);\n}\n\nexport function ModelInfo({ data }) {\n if (!data) return null;\n return h(\"p.model-name\", [\"Model: \", h(\"code.bp6-code\", data.name)]);\n}\n\nexport type MatchComponent = (props: { data: any }) => any;\n\ntype EntityTagProps = {\n data: EntityExt;\n highlighted?: boolean;\n active?: boolean;\n onClickType?: (type: EntityType) => void;\n matchComponent?: MatchComponent;\n};\n\nexport function EntityTag({\n data,\n highlighted = true,\n active = false,\n onClickType,\n matchComponent = null,\n}: EntityTagProps) {\n const { name, type, match } = data;\n\n const className = classNames(\n {\n matched: match != null,\n type: data.type?.name ?? \"lith\",\n },\n \"entity\",\n );\n\n const style = getTagStyle(type?.color, { highlighted, active });\n\n let _matchLink = null;\n if (match != null && matchComponent != null) {\n _matchLink = h(matchComponent, { data: match });\n }\n\n return h(Tag, { style, className }, [\n h(\"span.entity-name\", name),\n \" \",\n h(\n \"code.entity-type.bp6-code\",\n {\n onClick(evt) {\n if (active && onClickType != null) {\n onClickType(type);\n evt.stopPropagation();\n }\n },\n },\n [type?.name, _matchLink],\n ),\n ]);\n}\n\nfunction ExtractionInfo({\n data,\n matchComponent = null,\n}: {\n data: EntityExt;\n matchComponent: MatchComponent;\n}) {\n const children = data.children ?? [];\n\n return h(\"li.entity-row\", [\n h(EntityTag, { data, matchComponent }),\n h.if(children.length > 0)([\n h(\n \"ul.children\",\n children.map((d) => h(ExtractionInfo, { data: d, matchComponent })),\n ),\n ]),\n ]);\n}\n\nfunction HighlightedText(props: { text: string; highlights: Highlight[] }) {\n const { text, highlights = [] } = props;\n const parts = [];\n let start = 0;\n\n const sortedHighlights = highlights.sort((a, b) => a.start - b.start);\n const deconflictedHighlights = sortedHighlights.map((highlight, i) => {\n if (i === 0) return highlight;\n const prev = sortedHighlights[i - 1];\n if (highlight.start < prev.end) {\n highlight.start = prev.end;\n }\n return highlight;\n });\n\n for (const highlight of deconflictedHighlights) {\n const { start: s, end, ...rest } = highlight;\n parts.push(text.slice(start, s));\n parts.push(h(\"span.highlight\", { style: rest }, text.slice(s, end)));\n start = end;\n }\n parts.push(text.slice(start));\n return h(\"span\", parts);\n}\n\nfunction normalizeColor(hex8) {\n const background = useDarkMode().isEnabled ? \"#000000\" : \"#ffffff\";\n\n const r = parseInt(hex8.slice(1, 3), 16);\n const g = parseInt(hex8.slice(3, 5), 16);\n const b = parseInt(hex8.slice(5, 7), 16);\n const a = parseInt(hex8.slice(7, 9), 16) / 255;\n\n const bgR = parseInt(background.slice(1, 3), 16);\n const bgG = parseInt(background.slice(3, 5), 16);\n const bgB = parseInt(background.slice(5, 7), 16);\n\n const blend = (fg, bg) => Math.round((1 - a) * bg + a * fg);\n\n const blendedR = blend(r, bgR);\n const blendedG = blend(g, bgG);\n const blendedB = blend(b, bgB);\n\n return (\n \"#\" +\n blendedR.toString(16).padStart(2, \"0\") +\n blendedG.toString(16).padStart(2, \"0\") +\n blendedB.toString(16).padStart(2, \"0\")\n );\n}\n\nfunction isHighlighted(id: number, selectedNodes: number[], nodes: any[]) {\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":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const entities = "_entities_m1o0j_1";
|
|
4
|
+
const entity = "_entity_m1o0j_9";
|
|
5
|
+
const styles = {
|
|
6
|
+
entities,
|
|
7
|
+
entity
|
|
8
|
+
};
|
|
9
|
+
exports.default = styles;
|
|
10
|
+
exports.entities = entities;
|
|
11
|
+
exports.entity = entity;
|
|
12
|
+
//# sourceMappingURL=main.module.sass.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.module.sass.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.module.sass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type EntityType = {
|
|
2
|
+
name: string;
|
|
3
|
+
color: string;
|
|
4
|
+
id: number;
|
|
5
|
+
description?: string;
|
|
6
|
+
};
|
|
7
|
+
type Match = any;
|
|
8
|
+
export interface Entity {
|
|
9
|
+
id: number;
|
|
10
|
+
name: string;
|
|
11
|
+
type?: number;
|
|
12
|
+
indices: [number, number];
|
|
13
|
+
children: Entity[];
|
|
14
|
+
match?: Match;
|
|
15
|
+
}
|
|
16
|
+
export { EntityType };
|
|
17
|
+
export type Highlight = {
|
|
18
|
+
start: number;
|
|
19
|
+
end: number;
|
|
20
|
+
tag?: string;
|
|
21
|
+
text?: string;
|
|
22
|
+
backgroundColor?: string;
|
|
23
|
+
borderColor?: string;
|
|
24
|
+
id: number;
|
|
25
|
+
parents?: number[];
|
|
26
|
+
match?: Match;
|
|
27
|
+
};
|
|
28
|
+
export interface EntityExt extends Omit<Entity, "type" | "children"> {
|
|
29
|
+
type: EntityType;
|
|
30
|
+
children: EntityExt[];
|
|
31
|
+
parents?: number[];
|
|
32
|
+
}
|