tycho-components 0.36.10 → 0.37.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/dist/configs/useMessageUtils.js +1 -1
- package/dist/features/PageRender/PageRenderView.d.ts +2 -0
- package/dist/features/PageRender/PageRenderView.js +67 -0
- package/dist/features/PageRender/collapseElementsForTier.d.ts +12 -0
- package/dist/features/PageRender/collapseElementsForTier.js +262 -0
- package/dist/features/PageRender/editionTierOrder.d.ts +16 -0
- package/dist/features/PageRender/editionTierOrder.js +48 -0
- package/dist/features/PageRender/index.d.ts +4 -0
- package/dist/features/PageRender/index.js +4 -0
- package/dist/features/PageRender/tokenUtils.d.ts +4 -0
- package/dist/features/PageRender/tokenUtils.js +28 -0
- package/dist/features/PageRender/types.d.ts +62 -0
- package/dist/features/PageRender/types.js +9 -0
- package/dist/features/index.d.ts +2 -0
- package/dist/features/index.js +1 -0
- package/package.json +3 -3
|
@@ -14,7 +14,7 @@ export const getErrorMessageValue = ({ err, t, key }) => {
|
|
|
14
14
|
return translateErrorValue(t, key ?? "message", String(err));
|
|
15
15
|
}
|
|
16
16
|
if (err.response.status === 403) {
|
|
17
|
-
return t("error.access.authorization");
|
|
17
|
+
return t("error.access.authorization", { ns: "message" });
|
|
18
18
|
}
|
|
19
19
|
let errorKey = "";
|
|
20
20
|
if (err.response.data?.message) {
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { PageRenderViewProps } from './types';
|
|
2
|
+
export default function PageRenderView({ elements, selectedTier, corpus, document, displayTags, showLineNumbers, highlightSentenceUid, getDisplayValue, getTokenStyle, isTokenEdited, getParticipantName, getParticipantColor, onTokenClick, }: PageRenderViewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import collapseElementsForTier from './collapseElementsForTier';
|
|
4
|
+
import isTokenRefVisible, { tokenRefToToken } from './tokenUtils';
|
|
5
|
+
import { PageRenderElementType, } from './types';
|
|
6
|
+
export default function PageRenderView({ elements, selectedTier, corpus, document, displayTags = false, showLineNumbers = true, highlightSentenceUid, getDisplayValue, getTokenStyle, isTokenEdited, getParticipantName, getParticipantColor, onTokenClick, }) {
|
|
7
|
+
const collapsed = collapseElementsForTier(elements, selectedTier, corpus);
|
|
8
|
+
return (_jsx("div", { className: "page-render-elements", children: collapsed.map((item) => (_jsx(PageRenderElementItem, { item: item, highlight: highlightSentenceUid != null &&
|
|
9
|
+
sentenceUidForItem(item) === highlightSentenceUid, showLineNumbers: showLineNumbers, displayTags: displayTags, getDisplayValue: getDisplayValue, getTokenStyle: getTokenStyle, isTokenEdited: isTokenEdited, getParticipantName: getParticipantName, getParticipantColor: getParticipantColor, onTokenClick: onTokenClick, document: document }, item.key))) }));
|
|
10
|
+
}
|
|
11
|
+
function sentenceUidForItem(item) {
|
|
12
|
+
if (item.kind === 'collapsedJunction')
|
|
13
|
+
return item.token.uid;
|
|
14
|
+
if (item.kind === 'single' && item.element.token)
|
|
15
|
+
return item.element.token.uid;
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
function PageRenderElementItem({ item, highlight, showLineNumbers, displayTags, document, getDisplayValue, getTokenStyle, isTokenEdited, getParticipantName, getParticipantColor, onTokenClick, }) {
|
|
19
|
+
if (item.kind === 'collapsedJunction') {
|
|
20
|
+
return renderToken(item.token, item.splitIdx ?? 0, true, highlight, displayTags, getDisplayValue, getTokenStyle, isTokenEdited, onTokenClick);
|
|
21
|
+
}
|
|
22
|
+
const { element } = item;
|
|
23
|
+
switch (element.type) {
|
|
24
|
+
case PageRenderElementType.PARTICIPANT:
|
|
25
|
+
if (!element.participant)
|
|
26
|
+
return null;
|
|
27
|
+
return (_jsx("span", { className: "participant", style: getParticipantColor
|
|
28
|
+
? { backgroundColor: getParticipantColor(element.participant) }
|
|
29
|
+
: undefined, children: getParticipantName
|
|
30
|
+
? getParticipantName(element.participant)
|
|
31
|
+
: element.participant }));
|
|
32
|
+
case PageRenderElementType.LINE_BREAK:
|
|
33
|
+
return _jsx("hr", { className: "line-break" });
|
|
34
|
+
case PageRenderElementType.LINE_NUMBER:
|
|
35
|
+
if (!showLineNumbers || element.line == null)
|
|
36
|
+
return null;
|
|
37
|
+
return _jsx("span", { className: "line-break-number", children: element.line });
|
|
38
|
+
case PageRenderElementType.MARK:
|
|
39
|
+
if (!element.token)
|
|
40
|
+
return null;
|
|
41
|
+
return renderToken(element.token, 0, false, highlight, displayTags, getDisplayValue, getTokenStyle, isTokenEdited, onTokenClick, true);
|
|
42
|
+
case PageRenderElementType.JUNCTION_SPLIT:
|
|
43
|
+
if (!element.token)
|
|
44
|
+
return null;
|
|
45
|
+
return renderToken(element.token, element.idx ?? 0, true, highlight, displayTags, getDisplayValue, getTokenStyle, isTokenEdited, onTokenClick);
|
|
46
|
+
case PageRenderElementType.TOKEN:
|
|
47
|
+
if (!element.token)
|
|
48
|
+
return null;
|
|
49
|
+
return renderToken(element.token, 0, false, highlight, displayTags, getDisplayValue, getTokenStyle, isTokenEdited, onTokenClick);
|
|
50
|
+
default:
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function renderToken(ref, splitIdx, isSplit, highlight, displayTags, getDisplayValue, getTokenStyle, isTokenEdited, onTokenClick, isMark = false) {
|
|
55
|
+
const token = tokenRefToToken(ref);
|
|
56
|
+
const displaySplits = token.ec && token.split && !displayTags;
|
|
57
|
+
const visible = isMark || isTokenRefVisible(ref);
|
|
58
|
+
const tokenClass = cx('token', {
|
|
59
|
+
split: isSplit,
|
|
60
|
+
'd-none': !visible || !!displaySplits,
|
|
61
|
+
edited: isTokenEdited ? isTokenEdited(token) : !!ref.edited,
|
|
62
|
+
highlight,
|
|
63
|
+
mark: isMark,
|
|
64
|
+
});
|
|
65
|
+
const anchorId = highlight && ref.p === 1 ? 'selected' : undefined;
|
|
66
|
+
return (_jsxs("div", { id: anchorId, className: tokenClass, style: getTokenStyle?.(token), onClick: onTokenClick ? () => onTokenClick(ref, splitIdx) : undefined, children: [getDisplayValue(token, splitIdx), displayTags && (_jsxs("b", { className: "tag", children: ["/", token.split ? token.split.t : token.t] }))] }));
|
|
67
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CollapsedPageRenderElement, PageRenderElement } from './types';
|
|
2
|
+
import type { Corpus } from '../../configs/types/Corpus';
|
|
3
|
+
export declare function shouldSkipJunctionContinuationElement(elements: PageRenderElement[], index: number, selectedTier: string, corpus?: Corpus | null): boolean;
|
|
4
|
+
export declare function findSegmentationGroupBounds(elements: PageRenderElement[], index: number): {
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function shouldSkipSegmentationElement(elements: PageRenderElement[], index: number, selectedTier: string, corpus?: Corpus | null): boolean;
|
|
9
|
+
/** @deprecated Use shouldSkipSegmentationElement */
|
|
10
|
+
export declare function shouldSkipSegmentationToken(elements: PageRenderElement[], index: number, selectedTier: string, corpus?: Corpus | null): boolean;
|
|
11
|
+
export default function collapseElementsForTier(elements: PageRenderElement[], selectedTier: string, corpus?: Corpus | null): CollapsedPageRenderElement[];
|
|
12
|
+
export declare function isTokenBearingCollapsed(item: CollapsedPageRenderElement): boolean;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { isUnderSelected, JUNCTION_TIER, SEGMENTATION_TIER, } from './editionTierOrder';
|
|
2
|
+
import { PageRenderElementType, } from './types';
|
|
3
|
+
function sameJunctionGroup(a, b) {
|
|
4
|
+
if (a.type !== PageRenderElementType.JUNCTION_SPLIT ||
|
|
5
|
+
b.type !== PageRenderElementType.JUNCTION_SPLIT ||
|
|
6
|
+
!a.token ||
|
|
7
|
+
!b.token) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return a.token.uid === b.token.uid && a.token.p === b.token.p;
|
|
11
|
+
}
|
|
12
|
+
function hasJunctionFromRef(ref) {
|
|
13
|
+
const ops = ref.edition?.ops;
|
|
14
|
+
return ops !== undefined && ops[JUNCTION_TIER] !== undefined;
|
|
15
|
+
}
|
|
16
|
+
function hasSegmentationFromRef(ref) {
|
|
17
|
+
const ops = ref.edition?.ops;
|
|
18
|
+
return ops !== undefined && ops[SEGMENTATION_TIER] !== undefined;
|
|
19
|
+
}
|
|
20
|
+
function segmentationGroupKey(ref) {
|
|
21
|
+
return ref.edition?.sg || ref.edition?.id;
|
|
22
|
+
}
|
|
23
|
+
function sameSegmentationGroupRef(ref, uid, groupKey) {
|
|
24
|
+
return ref.uid === uid && segmentationGroupKey(ref) === groupKey;
|
|
25
|
+
}
|
|
26
|
+
function isJunctionEditionElement(element) {
|
|
27
|
+
if (!element.token)
|
|
28
|
+
return false;
|
|
29
|
+
if (element.type !== PageRenderElementType.TOKEN &&
|
|
30
|
+
element.type !== PageRenderElementType.JUNCTION_SPLIT) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return hasJunctionFromRef(element.token);
|
|
34
|
+
}
|
|
35
|
+
function getGlobalFirstJunctionPos(elements, uid, editionId) {
|
|
36
|
+
let firstP = null;
|
|
37
|
+
for (const element of elements) {
|
|
38
|
+
if (!isJunctionEditionElement(element))
|
|
39
|
+
continue;
|
|
40
|
+
const ref = element.token;
|
|
41
|
+
if (ref.uid !== uid || ref.edition?.id !== editionId)
|
|
42
|
+
continue;
|
|
43
|
+
if (firstP === null || ref.p < firstP) {
|
|
44
|
+
firstP = ref.p;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return firstP;
|
|
48
|
+
}
|
|
49
|
+
function getGlobalLastJunctionPos(elements, uid, editionId) {
|
|
50
|
+
let lastP = null;
|
|
51
|
+
for (const element of elements) {
|
|
52
|
+
if (!isJunctionEditionElement(element))
|
|
53
|
+
continue;
|
|
54
|
+
const ref = element.token;
|
|
55
|
+
if (ref.uid !== uid || ref.edition?.id !== editionId)
|
|
56
|
+
continue;
|
|
57
|
+
if (lastP === null || ref.p > lastP) {
|
|
58
|
+
lastP = ref.p;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return lastP;
|
|
62
|
+
}
|
|
63
|
+
function getGlobalLastSegmentationPos(elements, uid, groupKey) {
|
|
64
|
+
let lastP = null;
|
|
65
|
+
for (const element of elements) {
|
|
66
|
+
if (!isSegmentationEditionElement(element))
|
|
67
|
+
continue;
|
|
68
|
+
const ref = element.token;
|
|
69
|
+
if (!sameSegmentationGroupRef(ref, uid, groupKey))
|
|
70
|
+
continue;
|
|
71
|
+
if (lastP === null || ref.p > lastP) {
|
|
72
|
+
lastP = ref.p;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return lastP;
|
|
76
|
+
}
|
|
77
|
+
function hasVisibleEarlierJunctionHost(elements, index, selectedTier, corpus) {
|
|
78
|
+
const ref = elements[index].token;
|
|
79
|
+
const editionId = ref.edition?.id;
|
|
80
|
+
for (let i = 0; i < index; i += 1) {
|
|
81
|
+
const earlier = elements[i];
|
|
82
|
+
if (!isJunctionEditionElement(earlier))
|
|
83
|
+
continue;
|
|
84
|
+
const earlierRef = earlier.token;
|
|
85
|
+
if (earlierRef.uid !== ref.uid || earlierRef.edition?.id !== editionId) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (earlierRef.p >= ref.p)
|
|
89
|
+
continue;
|
|
90
|
+
if (shouldSkipSegmentationElement(elements, i, selectedTier, corpus))
|
|
91
|
+
continue;
|
|
92
|
+
if ((earlier.idx ?? 0) === 0)
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
export function shouldSkipJunctionContinuationElement(elements, index, selectedTier, corpus) {
|
|
98
|
+
const element = elements[index];
|
|
99
|
+
if (!isJunctionEditionElement(element)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
const ref = element.token;
|
|
103
|
+
const splitIdx = element.idx ?? 0;
|
|
104
|
+
const editionId = ref.edition?.id;
|
|
105
|
+
const segmentationGroup = segmentationGroupKey(ref);
|
|
106
|
+
const segmented = hasSegmentationFromRef(ref);
|
|
107
|
+
// Original layer: separated junction parts; dedupe hosts/suffixes when segmented
|
|
108
|
+
if (isUnderSelected(selectedTier, JUNCTION_TIER, corpus)) {
|
|
109
|
+
if (element.type === PageRenderElementType.JUNCTION_SPLIT &&
|
|
110
|
+
splitIdx > 0 &&
|
|
111
|
+
segmented) {
|
|
112
|
+
const lastP = getGlobalLastSegmentationPos(elements, ref.uid, segmentationGroup);
|
|
113
|
+
if (lastP !== null && ref.p < lastP) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (splitIdx === 0 &&
|
|
118
|
+
segmented &&
|
|
119
|
+
hasVisibleEarlierJunctionHost(elements, index, selectedTier, corpus)) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
// Junction tier or higher: one surface per struct token (idx 0 only; collapse merges splits)
|
|
125
|
+
if (element.type === PageRenderElementType.JUNCTION_SPLIT && splitIdx > 0) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
const lastP = segmented
|
|
129
|
+
? getGlobalLastSegmentationPos(elements, ref.uid, segmentationGroup) ??
|
|
130
|
+
getGlobalLastJunctionPos(elements, ref.uid, editionId)
|
|
131
|
+
: getGlobalLastJunctionPos(elements, ref.uid, editionId);
|
|
132
|
+
if (lastP === null) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
if (segmented &&
|
|
136
|
+
hasDistinctSegmentationOpsAcrossHosts(elements, ref.uid, segmentationGroup)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return ref.p !== lastP;
|
|
140
|
+
}
|
|
141
|
+
function isSegmentationEditionElement(element) {
|
|
142
|
+
if (!element.token)
|
|
143
|
+
return false;
|
|
144
|
+
if (element.type !== PageRenderElementType.TOKEN &&
|
|
145
|
+
element.type !== PageRenderElementType.JUNCTION_SPLIT) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return hasSegmentationFromRef(element.token);
|
|
149
|
+
}
|
|
150
|
+
function hasDistinctSegmentationOpsAcrossHosts(elements, uid, groupKey) {
|
|
151
|
+
const segValues = new Set();
|
|
152
|
+
for (const element of elements) {
|
|
153
|
+
if (!isSegmentationEditionElement(element))
|
|
154
|
+
continue;
|
|
155
|
+
const ref = element.token;
|
|
156
|
+
if (!sameSegmentationGroupRef(ref, uid, groupKey))
|
|
157
|
+
continue;
|
|
158
|
+
const seg = ref.edition?.ops?.seg;
|
|
159
|
+
if (seg !== undefined)
|
|
160
|
+
segValues.add(seg);
|
|
161
|
+
}
|
|
162
|
+
return segValues.size > 1;
|
|
163
|
+
}
|
|
164
|
+
function sameSegmentationEditionGroup(a, b) {
|
|
165
|
+
if (!isSegmentationEditionElement(a) || !isSegmentationEditionElement(b)) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
const aRef = a.token;
|
|
169
|
+
const bRef = b.token;
|
|
170
|
+
return (aRef.uid === bRef.uid &&
|
|
171
|
+
segmentationGroupKey(aRef) === segmentationGroupKey(bRef));
|
|
172
|
+
}
|
|
173
|
+
export function findSegmentationGroupBounds(elements, index) {
|
|
174
|
+
if (!isSegmentationEditionElement(elements[index])) {
|
|
175
|
+
return { start: index, end: index };
|
|
176
|
+
}
|
|
177
|
+
let start = index;
|
|
178
|
+
while (start > 0 &&
|
|
179
|
+
sameSegmentationEditionGroup(elements[start - 1], elements[index])) {
|
|
180
|
+
start -= 1;
|
|
181
|
+
}
|
|
182
|
+
let end = index;
|
|
183
|
+
while (end < elements.length - 1 &&
|
|
184
|
+
sameSegmentationEditionGroup(elements[end + 1], elements[index])) {
|
|
185
|
+
end += 1;
|
|
186
|
+
}
|
|
187
|
+
return { start, end };
|
|
188
|
+
}
|
|
189
|
+
function getLastSegmentationPosInGroup(elements, start, end) {
|
|
190
|
+
let lastP = elements[start].token.p;
|
|
191
|
+
for (let i = start + 1; i <= end; i += 1) {
|
|
192
|
+
const p = elements[i].token?.p;
|
|
193
|
+
if (p !== undefined && p > lastP) {
|
|
194
|
+
lastP = p;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return lastP;
|
|
198
|
+
}
|
|
199
|
+
export function shouldSkipSegmentationElement(elements, index, selectedTier, corpus) {
|
|
200
|
+
if (!isUnderSelected(selectedTier, SEGMENTATION_TIER, corpus)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
const element = elements[index];
|
|
204
|
+
if (!isSegmentationEditionElement(element)) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const { start, end } = findSegmentationGroupBounds(elements, index);
|
|
208
|
+
const lastP = getLastSegmentationPosInGroup(elements, start, end);
|
|
209
|
+
return element.token.p < lastP;
|
|
210
|
+
}
|
|
211
|
+
/** @deprecated Use shouldSkipSegmentationElement */
|
|
212
|
+
export function shouldSkipSegmentationToken(elements, index, selectedTier, corpus) {
|
|
213
|
+
return shouldSkipSegmentationElement(elements, index, selectedTier, corpus);
|
|
214
|
+
}
|
|
215
|
+
export default function collapseElementsForTier(elements, selectedTier, corpus) {
|
|
216
|
+
const showJunctionSplits = isUnderSelected(selectedTier, JUNCTION_TIER, corpus);
|
|
217
|
+
const collapsed = [];
|
|
218
|
+
let index = 0;
|
|
219
|
+
while (index < elements.length) {
|
|
220
|
+
const element = elements[index];
|
|
221
|
+
if (shouldSkipSegmentationElement(elements, index, selectedTier, corpus)) {
|
|
222
|
+
index += 1;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (shouldSkipJunctionContinuationElement(elements, index, selectedTier, corpus)) {
|
|
226
|
+
index += 1;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (!showJunctionSplits &&
|
|
230
|
+
element.type === PageRenderElementType.JUNCTION_SPLIT &&
|
|
231
|
+
element.token) {
|
|
232
|
+
const token = element.token;
|
|
233
|
+
let end = index + 1;
|
|
234
|
+
while (end < elements.length &&
|
|
235
|
+
sameJunctionGroup(element, elements[end])) {
|
|
236
|
+
end += 1;
|
|
237
|
+
}
|
|
238
|
+
collapsed.push({
|
|
239
|
+
kind: 'collapsedJunction',
|
|
240
|
+
token,
|
|
241
|
+
splitIdx: element.idx ?? 0,
|
|
242
|
+
key: `junction_${token.uid}_${token.p}_${index}`,
|
|
243
|
+
});
|
|
244
|
+
index = end;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
collapsed.push({
|
|
248
|
+
kind: 'single',
|
|
249
|
+
element,
|
|
250
|
+
key: `${element.type}_${index}`,
|
|
251
|
+
});
|
|
252
|
+
index += 1;
|
|
253
|
+
}
|
|
254
|
+
return collapsed;
|
|
255
|
+
}
|
|
256
|
+
export function isTokenBearingCollapsed(item) {
|
|
257
|
+
if (item.kind === 'collapsedJunction')
|
|
258
|
+
return true;
|
|
259
|
+
const { element } = item;
|
|
260
|
+
return (element.type === PageRenderElementType.TOKEN ||
|
|
261
|
+
element.type === PageRenderElementType.JUNCTION_SPLIT);
|
|
262
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Corpus } from '../../configs/types/Corpus';
|
|
2
|
+
export declare const SEGMENTATION_TIER = "seg";
|
|
3
|
+
export declare const JUNCTION_TIER = "jun";
|
|
4
|
+
export declare function getEditionTierOrder(corpus?: Corpus | null): readonly string[];
|
|
5
|
+
/** Default display order (structural prefix + default corpus tiers). */
|
|
6
|
+
export declare const EDITION_TIER_ORDER: readonly string[];
|
|
7
|
+
export declare function isUnderSelected(selected: string, tier: string, corpus?: Corpus | null): boolean;
|
|
8
|
+
/** Highest edition tier present on the token from junction down to the selected tier. */
|
|
9
|
+
export declare function resolveHighestEditionTierForDisplay(ops: Record<string, string> | undefined, selectedTier: string, corpus?: Corpus | null): string | null;
|
|
10
|
+
/** Alias: highest tier from junction through the selected tier (inclusive). */
|
|
11
|
+
export declare function resolveEffectiveEditionTierForDisplay(ops: Record<string, string> | undefined, selectedTier: string, corpus?: Corpus | null): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Junction + segmentation with no higher edition up to the selected tier → segmentation display.
|
|
14
|
+
* When e.g. padronization exists above segmentation, that layer is shown instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare function shouldApplySegmentationOverJunction(ops: Record<string, string> | undefined, selectedTier: string, corpus?: Corpus | null): boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import EditionTierUtils from '../../functions/EditionTierUtils';
|
|
2
|
+
export const SEGMENTATION_TIER = 'seg';
|
|
3
|
+
export const JUNCTION_TIER = 'jun';
|
|
4
|
+
export function getEditionTierOrder(corpus) {
|
|
5
|
+
return EditionTierUtils.getDisplayTierOrder(corpus);
|
|
6
|
+
}
|
|
7
|
+
/** Default display order (structural prefix + default corpus tiers). */
|
|
8
|
+
export const EDITION_TIER_ORDER = getEditionTierOrder(null);
|
|
9
|
+
export function isUnderSelected(selected, tier, corpus) {
|
|
10
|
+
const order = getEditionTierOrder(corpus);
|
|
11
|
+
const s = order.indexOf(selected);
|
|
12
|
+
const t = order.indexOf(tier);
|
|
13
|
+
if (s === -1 || t === -1)
|
|
14
|
+
return false;
|
|
15
|
+
return s < t;
|
|
16
|
+
}
|
|
17
|
+
/** Highest edition tier present on the token from junction down to the selected tier. */
|
|
18
|
+
export function resolveHighestEditionTierForDisplay(ops, selectedTier, corpus) {
|
|
19
|
+
const order = getEditionTierOrder(corpus);
|
|
20
|
+
const selectedIdx = order.indexOf(selectedTier);
|
|
21
|
+
if (selectedIdx <= 0)
|
|
22
|
+
return null;
|
|
23
|
+
let effective = null;
|
|
24
|
+
for (let i = 1; i <= selectedIdx; i += 1) {
|
|
25
|
+
const tier = order[i];
|
|
26
|
+
if (ops?.[tier] !== undefined) {
|
|
27
|
+
effective = tier;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return effective;
|
|
31
|
+
}
|
|
32
|
+
/** Alias: highest tier from junction through the selected tier (inclusive). */
|
|
33
|
+
export function resolveEffectiveEditionTierForDisplay(ops, selectedTier, corpus) {
|
|
34
|
+
return resolveHighestEditionTierForDisplay(ops, selectedTier, corpus);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Junction + segmentation with no higher edition up to the selected tier → segmentation display.
|
|
38
|
+
* When e.g. padronization exists above segmentation, that layer is shown instead.
|
|
39
|
+
*/
|
|
40
|
+
export function shouldApplySegmentationOverJunction(ops, selectedTier, corpus) {
|
|
41
|
+
if (ops?.[JUNCTION_TIER] === undefined ||
|
|
42
|
+
ops?.[SEGMENTATION_TIER] === undefined ||
|
|
43
|
+
isUnderSelected(selectedTier, SEGMENTATION_TIER, corpus)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return (resolveEffectiveEditionTierForDisplay(ops, selectedTier, corpus) ===
|
|
47
|
+
SEGMENTATION_TIER);
|
|
48
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default function isTokenRefVisible(ref) {
|
|
2
|
+
return ref.v !== '' && (!ref.ec || (ref.ec && !!ref.split));
|
|
3
|
+
}
|
|
4
|
+
export function tokenRefToToken(ref) {
|
|
5
|
+
const token = {
|
|
6
|
+
tid: ref.tid,
|
|
7
|
+
p: ref.p,
|
|
8
|
+
v: ref.v,
|
|
9
|
+
t: ref.t,
|
|
10
|
+
edited: ref.edited,
|
|
11
|
+
cid: ref.cid,
|
|
12
|
+
bid: ref.bid,
|
|
13
|
+
mid: ref.mid,
|
|
14
|
+
ns: ref.ns,
|
|
15
|
+
review: ref.review,
|
|
16
|
+
ec: ref.ec,
|
|
17
|
+
edition: ref.edition,
|
|
18
|
+
format: ref.format,
|
|
19
|
+
split: ref.split,
|
|
20
|
+
};
|
|
21
|
+
if (ref.edition) {
|
|
22
|
+
token.edition = ref.edition;
|
|
23
|
+
if (ref.edited) {
|
|
24
|
+
token.eid = ref.edition.id || 'edition';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return token;
|
|
28
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Corpus } from '../../configs/types/Corpus';
|
|
3
|
+
import type Document from '../../configs/types/Document';
|
|
4
|
+
import type { Edition, Format, Split, Token } from '../../configs/types/Struct';
|
|
5
|
+
export declare enum PageRenderElementType {
|
|
6
|
+
MARK = "MARK",
|
|
7
|
+
TOKEN = "TOKEN",
|
|
8
|
+
JUNCTION_SPLIT = "JUNCTION_SPLIT",
|
|
9
|
+
LINE_BREAK = "LINE_BREAK",
|
|
10
|
+
LINE_NUMBER = "LINE_NUMBER",
|
|
11
|
+
PARTICIPANT = "PARTICIPANT"
|
|
12
|
+
}
|
|
13
|
+
export type TokenRef = {
|
|
14
|
+
uid: string;
|
|
15
|
+
tid?: string;
|
|
16
|
+
p: number;
|
|
17
|
+
v: string;
|
|
18
|
+
t?: string;
|
|
19
|
+
edited?: boolean;
|
|
20
|
+
cid?: string;
|
|
21
|
+
bid?: string;
|
|
22
|
+
mid?: string;
|
|
23
|
+
ns?: boolean;
|
|
24
|
+
review?: boolean;
|
|
25
|
+
ec?: boolean;
|
|
26
|
+
edition?: Edition;
|
|
27
|
+
format?: Format;
|
|
28
|
+
split?: Split;
|
|
29
|
+
};
|
|
30
|
+
export type PageRenderElement = {
|
|
31
|
+
type: PageRenderElementType;
|
|
32
|
+
idx?: number;
|
|
33
|
+
line?: number;
|
|
34
|
+
mstart?: boolean;
|
|
35
|
+
participant?: string;
|
|
36
|
+
token?: TokenRef;
|
|
37
|
+
};
|
|
38
|
+
export type CollapsedPageRenderElement = {
|
|
39
|
+
kind: 'single';
|
|
40
|
+
element: PageRenderElement;
|
|
41
|
+
key: string;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'collapsedJunction';
|
|
44
|
+
token: TokenRef;
|
|
45
|
+
splitIdx?: number;
|
|
46
|
+
key: string;
|
|
47
|
+
};
|
|
48
|
+
export type PageRenderViewProps = {
|
|
49
|
+
elements: PageRenderElement[];
|
|
50
|
+
selectedTier: string;
|
|
51
|
+
corpus?: Corpus | null;
|
|
52
|
+
document?: Document | null;
|
|
53
|
+
displayTags?: boolean;
|
|
54
|
+
showLineNumbers?: boolean;
|
|
55
|
+
highlightSentenceUid?: string;
|
|
56
|
+
getDisplayValue: (token: Token, splitIdx?: number) => ReactNode;
|
|
57
|
+
getTokenStyle?: (token: Token) => React.CSSProperties;
|
|
58
|
+
isTokenEdited?: (token: Token) => boolean;
|
|
59
|
+
getParticipantName?: (code: string) => string;
|
|
60
|
+
getParticipantColor?: (code: string) => string;
|
|
61
|
+
onTokenClick?: (ref: TokenRef, splitIdx?: number) => void;
|
|
62
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var PageRenderElementType;
|
|
2
|
+
(function (PageRenderElementType) {
|
|
3
|
+
PageRenderElementType["MARK"] = "MARK";
|
|
4
|
+
PageRenderElementType["TOKEN"] = "TOKEN";
|
|
5
|
+
PageRenderElementType["JUNCTION_SPLIT"] = "JUNCTION_SPLIT";
|
|
6
|
+
PageRenderElementType["LINE_BREAK"] = "LINE_BREAK";
|
|
7
|
+
PageRenderElementType["LINE_NUMBER"] = "LINE_NUMBER";
|
|
8
|
+
PageRenderElementType["PARTICIPANT"] = "PARTICIPANT";
|
|
9
|
+
})(PageRenderElementType || (PageRenderElementType = {}));
|
package/dist/features/index.d.ts
CHANGED
|
@@ -13,3 +13,5 @@ export type { SearchCriteria } from "./TreeView/TreeViewSearch/TreeViewSearch";
|
|
|
13
13
|
export { default as CytoscapeMenuCanvas } from "./CytoscapeMenu/CytoscapeMenuCanvas";
|
|
14
14
|
export { registerCytoscapeContextMenus, contextMenus } from "./CytoscapeMenu";
|
|
15
15
|
export type { CytoscapeContextMenuOptions, MenuItemOption, ContextMenusInstance, } from "./CytoscapeMenu";
|
|
16
|
+
export { PageRenderView, collapseElementsForTier, tokenRefToToken, isTokenRefVisible, } from "./PageRender";
|
|
17
|
+
export type { PageRenderElement, PageRenderElementType, PageRenderViewProps, TokenRef, CollapsedPageRenderElement, } from "./PageRender";
|
package/dist/features/index.js
CHANGED
|
@@ -9,3 +9,4 @@ export { default as SyntreesCytoscape } from "./TreeView/cytoscape/SyntreesCytos
|
|
|
9
9
|
export { default as TreeViewSearch } from "./TreeView/TreeViewSearch/TreeViewSearch";
|
|
10
10
|
export { default as CytoscapeMenuCanvas } from "./CytoscapeMenu/CytoscapeMenuCanvas";
|
|
11
11
|
export { registerCytoscapeContextMenus, contextMenus } from "./CytoscapeMenu";
|
|
12
|
+
export { PageRenderView, collapseElementsForTier, tokenRefToToken, isTokenRefVisible, } from "./PageRender";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tycho-components",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.37.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"react-i18next": "^13.0.2",
|
|
83
83
|
"react-router-dom": "^6.14.2",
|
|
84
84
|
"react-toastify": "^9.1.3",
|
|
85
|
-
"tycho-storybook": "0.10.
|
|
85
|
+
"tycho-storybook": "0.10.15",
|
|
86
86
|
"wavesurfer-react": "^2.2.2",
|
|
87
87
|
"wavesurfer.js": "^6.6.3"
|
|
88
88
|
},
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"react-toastify": "^9.1.3",
|
|
112
112
|
"sass-embedded": "^1.97.2",
|
|
113
113
|
"storybook": "^10.1.11",
|
|
114
|
-
"tycho-storybook": "^0.10.
|
|
114
|
+
"tycho-storybook": "^0.10.15",
|
|
115
115
|
"typescript": "^5.7.3",
|
|
116
116
|
"vite": "^7.0.0",
|
|
117
117
|
"vitest": "^3.2.6",
|