@soomo/react-text-annotator 3.0.0-staging.9 → 3.1.0-staging.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/TextAnnotator.d.ts +4 -5
- package/dist/TextAnnotator.d.ts.map +1 -1
- package/dist/TextAnnotatorPlugin.d.ts +1 -2
- package/dist/TextAnnotatorPopup/TextAnnotatorPopup.d.ts +15 -0
- package/dist/TextAnnotatorPopup/TextAnnotatorPopup.d.ts.map +1 -0
- package/dist/TextAnnotatorPopup/index.d.ts +2 -0
- package/dist/TextAnnotatorPopup/index.d.ts.map +1 -0
- package/dist/TextAnnotatorPopup/isMobile.d.ts +2 -0
- package/dist/TextAnnotatorPopup/isMobile.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useAnnouncePopupNavigation.d.ts +10 -0
- package/dist/hooks/useAnnouncePopupNavigation.d.ts.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/react-text-annotator.css +31 -1
- package/dist/react-text-annotator.es.js +9 -5
- package/dist/react-text-annotator.es.js.map +1 -1
- package/dist/react-text-annotator.es10.js +442 -521
- package/dist/react-text-annotator.es10.js.map +1 -1
- package/dist/react-text-annotator.es11.js +9 -488
- package/dist/react-text-annotator.es11.js.map +1 -1
- package/dist/react-text-annotator.es12.js +1448 -2
- package/dist/react-text-annotator.es12.js.map +1 -1
- package/dist/react-text-annotator.es14.js +238 -891
- package/dist/react-text-annotator.es14.js.map +1 -1
- package/dist/react-text-annotator.es15.js +554 -197
- package/dist/react-text-annotator.es15.js.map +1 -1
- package/dist/react-text-annotator.es16.js +72 -126
- package/dist/react-text-annotator.es16.js.map +1 -1
- package/dist/react-text-annotator.es17.js +43 -112
- package/dist/react-text-annotator.es17.js.map +1 -1
- package/dist/react-text-annotator.es18.js +2 -309
- package/dist/react-text-annotator.es18.js.map +1 -1
- package/dist/react-text-annotator.es19.js +29 -56
- package/dist/react-text-annotator.es19.js.map +1 -1
- package/dist/react-text-annotator.es2.js +2 -2
- package/dist/react-text-annotator.es20.js +897 -19
- package/dist/react-text-annotator.es20.js.map +1 -1
- package/dist/react-text-annotator.es23.js +113 -120
- package/dist/react-text-annotator.es23.js.map +1 -1
- package/dist/react-text-annotator.es24.js +276 -519
- package/dist/react-text-annotator.es24.js.map +1 -1
- package/dist/react-text-annotator.es25.js +61 -0
- package/dist/react-text-annotator.es25.js.map +1 -0
- package/dist/react-text-annotator.es26.js +23 -0
- package/dist/react-text-annotator.es26.js.map +1 -0
- package/dist/react-text-annotator.es27.js +130 -0
- package/dist/react-text-annotator.es27.js.map +1 -0
- package/dist/react-text-annotator.es28.js +167 -0
- package/dist/react-text-annotator.es28.js.map +1 -0
- package/dist/react-text-annotator.es29.js +314 -0
- package/dist/react-text-annotator.es29.js.map +1 -0
- package/dist/react-text-annotator.es3.js +2 -2
- package/dist/react-text-annotator.es30.js +152 -0
- package/dist/react-text-annotator.es30.js.map +1 -0
- package/dist/react-text-annotator.es31.js +566 -0
- package/dist/react-text-annotator.es31.js.map +1 -0
- package/dist/react-text-annotator.es4.js +38 -28
- package/dist/react-text-annotator.es4.js.map +1 -1
- package/dist/react-text-annotator.es5.js +24 -72
- package/dist/react-text-annotator.es5.js.map +1 -1
- package/dist/react-text-annotator.es6.js +127 -10
- package/dist/react-text-annotator.es6.js.map +1 -1
- package/dist/react-text-annotator.es7.js +546 -1
- package/dist/react-text-annotator.es7.js.map +1 -1
- package/dist/react-text-annotator.es8.js +10 -24
- package/dist/react-text-annotator.es8.js.map +1 -1
- package/dist/tei/TEIAnnotator.d.ts +2 -3
- package/package.json +23 -17
- package/dist/TextAnnotatorPopup.d.ts +0 -15
- package/dist/TextAnnotatorPopup.d.ts.map +0 -1
- package/dist/react-text-annotator.es13.js +0 -38
- package/dist/react-text-annotator.es13.js.map +0 -1
- package/dist/react-text-annotator.es9.js +0 -199
- package/dist/react-text-annotator.es9.js.map +0 -1
- package/dist/utils.d.ts +0 -14
- package/dist/utils.d.ts.map +0 -1
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { useCallback, useLayoutEffect, useMemo, useRef, useEffect } from "react";
|
|
2
|
+
import { useAnnotationStore, useSelection, Origin } from "@annotorious/react";
|
|
3
|
+
import { announce as $319e236875307eab$export$a9b970dcc4ae71a9, destroyAnnouncer as $319e236875307eab$export$d8686216b8b81b2f } from "./react-text-annotator.es16.js";
|
|
4
|
+
import { exhaustiveUniqueRandom } from "./react-text-annotator.es17.js";
|
|
5
|
+
const useAnnouncePopupNavigation = (args) => {
|
|
6
|
+
const {
|
|
7
|
+
message = "Press Tab to move to Notes Dialog",
|
|
8
|
+
idle = 700,
|
|
9
|
+
floatingOpen,
|
|
10
|
+
disabled = false
|
|
11
|
+
} = args;
|
|
12
|
+
const store = useAnnotationStore();
|
|
13
|
+
const { event } = useSelection();
|
|
14
|
+
const uniqueRandom = useCallback(exhaustiveUniqueRandom(1, 1e4), []);
|
|
15
|
+
useLayoutEffect(() => {
|
|
16
|
+
if (disabled || !message) return;
|
|
17
|
+
$319e236875307eab$export$a9b970dcc4ae71a9("", "polite");
|
|
18
|
+
return () => $319e236875307eab$export$d8686216b8b81b2f();
|
|
19
|
+
}, [disabled, message]);
|
|
20
|
+
const announcementSeed = useMemo(() => floatingOpen ? uniqueRandom() : 0, [floatingOpen]);
|
|
21
|
+
const announcePopupNavigation = useCallback(() => {
|
|
22
|
+
const uniqueSpaces = Array.from({ length: announcementSeed }).map(() => " ").join("");
|
|
23
|
+
$319e236875307eab$export$a9b970dcc4ae71a9(`${message} ${uniqueSpaces}`, "polite");
|
|
24
|
+
}, [message, announcementSeed]);
|
|
25
|
+
const idleTimeoutRef = useRef(null);
|
|
10
26
|
useEffect(() => {
|
|
11
|
-
if (!
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}, [
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (!anno)
|
|
25
|
-
return;
|
|
26
|
-
anno.setFilter(props.filter);
|
|
27
|
-
}, [anno, props.filter]);
|
|
28
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: el, className, children });
|
|
27
|
+
if (disabled || !floatingOpen || !message) return;
|
|
28
|
+
const scheduleIdleAnnouncement = () => {
|
|
29
|
+
clearTimeout(idleTimeoutRef.current);
|
|
30
|
+
idleTimeoutRef.current = setTimeout(announcePopupNavigation, idle);
|
|
31
|
+
};
|
|
32
|
+
scheduleIdleAnnouncement();
|
|
33
|
+
store.observe(scheduleIdleAnnouncement, { origin: Origin.LOCAL });
|
|
34
|
+
return () => {
|
|
35
|
+
clearTimeout(idleTimeoutRef.current);
|
|
36
|
+
store.unobserve(scheduleIdleAnnouncement);
|
|
37
|
+
};
|
|
38
|
+
}, [disabled, floatingOpen, event == null ? void 0 : event.type, message, announcePopupNavigation, store]);
|
|
29
39
|
};
|
|
30
40
|
export {
|
|
31
|
-
|
|
41
|
+
useAnnouncePopupNavigation
|
|
32
42
|
};
|
|
33
43
|
//# sourceMappingURL=react-text-annotator.es4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-text-annotator.es4.js","sources":["../src/
|
|
1
|
+
{"version":3,"file":"react-text-annotator.es4.js","sources":["../src/hooks/useAnnouncePopupNavigation.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport { Origin, useAnnotationStore, useSelection } from '@annotorious/react';\nimport type { TextAnnotation } from '@recogito/text-annotator';\nimport { announce, destroyAnnouncer } from '@react-aria/live-announcer';\nimport { exhaustiveUniqueRandom } from 'unique-random';\n\ninterface AnnouncePopupOpeningArgs {\n message?: string;\n idle?: number;\n floatingOpen: boolean;\n floatingFocused?: boolean;\n disabled?: boolean;\n}\n\nexport const useAnnouncePopupNavigation = (args: AnnouncePopupOpeningArgs) => {\n const {\n message = 'Press Tab to move to Notes Dialog',\n idle = 700,\n floatingOpen,\n disabled = false\n } = args;\n\n const store = useAnnotationStore();\n const { event } = useSelection<TextAnnotation>();\n\n // Generate random numbers that do not repeat until the entire 1-10000 range has appeared\n const uniqueRandom = useCallback(exhaustiveUniqueRandom(1, 10000), []);\n\n /**\n * Initialize the `LiveAnnouncer` class and\n * its `polite` announcements live area\n */\n useLayoutEffect(() => {\n if (disabled || !message) return;\n\n announce('', 'polite');\n return () => destroyAnnouncer();\n }, [disabled, message]);\n\n /**\n * Screen reader requires messages to always be unique!\n * Otherwise, the hint will be announced once per page.\n */\n const announcementSeed = useMemo(() => floatingOpen ? uniqueRandom() : 0, [floatingOpen]);\n\n const announcePopupNavigation = useCallback(() => {\n /**\n * To imitate the uniqueness of the announced message\n * w/o mutating it - we can append spaces at the end.\n */\n const uniqueSpaces = Array.from({ length: announcementSeed }).map(() => ' ').join('');\n announce(`${message} ${uniqueSpaces}`, 'polite');\n }, [message, announcementSeed]);\n\n const idleTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (disabled || !floatingOpen || !message) return;\n\n const scheduleIdleAnnouncement = () => {\n clearTimeout(idleTimeoutRef.current);\n idleTimeoutRef.current = setTimeout(announcePopupNavigation, idle);\n };\n\n scheduleIdleAnnouncement();\n store.observe(scheduleIdleAnnouncement, { origin: Origin.LOCAL });\n\n return () => {\n clearTimeout(idleTimeoutRef.current);\n store.unobserve(scheduleIdleAnnouncement);\n };\n }, [disabled, floatingOpen, event?.type, message, announcePopupNavigation, store]);\n\n};\n"],"names":["announce","destroyAnnouncer"],"mappings":";;;;AAea,MAAA,6BAA6B,CAAC,SAAmC;AACtE,QAAA;AAAA,IACJ,UAAU;AAAA,IACV,OAAO;AAAA,IACP;AAAA,IACA,WAAW;AAAA,EACT,IAAA;AAEJ,QAAM,QAAQ;AACR,QAAA,EAAE,UAAU;AAGlB,QAAM,eAAe,YAAY,uBAAuB,GAAG,GAAK,GAAG,CAAA,CAAE;AAMrE,kBAAgB,MAAM;AAChB,QAAA,YAAY,CAAC,QAAS;AAE1BA,8CAAS,IAAI,QAAQ;AACrB,WAAO,MAAMC,0CAAiB;AAAA,EAAA,GAC7B,CAAC,UAAU,OAAO,CAAC;AAMhB,QAAA,mBAAmB,QAAQ,MAAM,eAAe,iBAAiB,GAAG,CAAC,YAAY,CAAC;AAElF,QAAA,0BAA0B,YAAY,MAAM;AAKhD,UAAM,eAAe,MAAM,KAAK,EAAE,QAAQ,iBAAA,CAAkB,EAAE,IAAI,MAAM,GAAG,EAAE,KAAK,EAAE;AACpFD,8CAAS,GAAG,OAAO,IAAI,YAAY,IAAI,QAAQ;AAAA,EAAA,GAC9C,CAAC,SAAS,gBAAgB,CAAC;AAExB,QAAA,iBAAiB,OAA6C,IAAI;AAExE,YAAU,MAAM;AACd,QAAI,YAAY,CAAC,gBAAgB,CAAC,QAAS;AAE3C,UAAM,2BAA2B,MAAM;AACrC,mBAAa,eAAe,OAAO;AACpB,qBAAA,UAAU,WAAW,yBAAyB,IAAI;AAAA,IAAA;AAG1C;AACzB,UAAM,QAAQ,0BAA0B,EAAE,QAAQ,OAAO,OAAO;AAEhE,WAAO,MAAM;AACX,mBAAa,eAAe,OAAO;AACnC,YAAM,UAAU,wBAAwB;AAAA,IAAA;AAAA,EAC1C,GACC,CAAC,UAAU,cAAc,+BAAO,MAAM,SAAS,yBAAyB,KAAK,CAAC;AAEnF;"}
|
|
@@ -1,77 +1,29 @@
|
|
|
1
|
-
import { j as jsxRuntimeExports } from "./react-text-annotator.
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const { refs, floatingStyles, update } = useFloating({
|
|
12
|
-
open: isOpen,
|
|
13
|
-
onOpenChange: setIsOpen,
|
|
14
|
-
middleware: [
|
|
15
|
-
autoPlacement({ crossAxis: true, padding: 5 }),
|
|
16
|
-
inline(),
|
|
17
|
-
offset(5),
|
|
18
|
-
shift({ crossAxis: true, padding: 5 })
|
|
19
|
-
],
|
|
20
|
-
whileElementsMounted: autoUpdate
|
|
21
|
-
});
|
|
1
|
+
import { j as jsxRuntimeExports } from "./react-text-annotator.es8.js";
|
|
2
|
+
import { useRef, useContext, useEffect } from "react";
|
|
3
|
+
import { AnnotoriousContext } from "@annotorious/react";
|
|
4
|
+
import { createTextAnnotator } from "@soomo/text-annotator";
|
|
5
|
+
/* empty css */
|
|
6
|
+
const TextAnnotator = (props) => {
|
|
7
|
+
const el = useRef(null);
|
|
8
|
+
const { className, children, ...opts } = props;
|
|
9
|
+
const { style, filter, user, annotatingEnabled, userSelectAction } = opts;
|
|
10
|
+
const { anno, setAnno } = useContext(AnnotoriousContext);
|
|
22
11
|
useEffect(() => {
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
useEffect(() =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
refs.setReference({
|
|
37
|
-
getBoundingClientRect: () => {
|
|
38
|
-
return range.getBoundingClientRect();
|
|
39
|
-
},
|
|
40
|
-
getClientRects: () => {
|
|
41
|
-
const rect = mousePos ? getClosestRect(range.getClientRects(), mousePos) : range.getClientRects()[0];
|
|
42
|
-
return toClientRects(rect);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}, [open, selected, mousePos]);
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
const onPointerUp = (event) => {
|
|
50
|
-
const { clientX, clientY } = event;
|
|
51
|
-
setMousePos({ x: clientX, y: clientY });
|
|
52
|
-
};
|
|
53
|
-
const config = { attributes: true, childList: true, subtree: true };
|
|
54
|
-
const mutationObserver = new MutationObserver(() => update());
|
|
55
|
-
mutationObserver.observe(document.body, config);
|
|
56
|
-
window.document.addEventListener("scroll", update, true);
|
|
57
|
-
window.document.addEventListener("pointerup", onPointerUp);
|
|
58
|
-
return () => {
|
|
59
|
-
mutationObserver.disconnect();
|
|
60
|
-
window.document.removeEventListener("scroll", update, true);
|
|
61
|
-
window.document.removeEventListener("pointerup", onPointerUp);
|
|
62
|
-
};
|
|
63
|
-
}, [update]);
|
|
64
|
-
return isOpen && selected.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65
|
-
"div",
|
|
66
|
-
{
|
|
67
|
-
className: "annotation-popup text-annotation-popup not-annotatable",
|
|
68
|
-
ref: refs.setFloating,
|
|
69
|
-
style: floatingStyles,
|
|
70
|
-
children: props.popup({ selected })
|
|
71
|
-
}
|
|
72
|
-
);
|
|
12
|
+
if (!setAnno) return;
|
|
13
|
+
const adapter = typeof opts.adapter === "function" ? opts.adapter(el.current) : opts.adapter;
|
|
14
|
+
const anno2 = createTextAnnotator(el.current, { ...opts, adapter });
|
|
15
|
+
setAnno(anno2);
|
|
16
|
+
return () => anno2.destroy();
|
|
17
|
+
}, [setAnno]);
|
|
18
|
+
useEffect(() => anno == null ? void 0 : anno.setStyle(style), [anno, style]);
|
|
19
|
+
useEffect(() => anno == null ? void 0 : anno.setFilter(filter), [anno, filter]);
|
|
20
|
+
useEffect(() => anno == null ? void 0 : anno.setFilter(filter), [anno, filter]);
|
|
21
|
+
useEffect(() => anno == null ? void 0 : anno.setUserSelectAction(userSelectAction), [anno, userSelectAction]);
|
|
22
|
+
useEffect(() => anno == null ? void 0 : anno.setUser(user), [anno, user]);
|
|
23
|
+
useEffect(() => anno == null ? void 0 : anno.setAnnotatingEnabled(annotatingEnabled), [anno, annotatingEnabled]);
|
|
24
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: el, className, children });
|
|
73
25
|
};
|
|
74
26
|
export {
|
|
75
|
-
|
|
27
|
+
TextAnnotator
|
|
76
28
|
};
|
|
77
29
|
//# sourceMappingURL=react-text-annotator.es5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-text-annotator.es5.js","sources":["../src/
|
|
1
|
+
{"version":3,"file":"react-text-annotator.es5.js","sources":["../src/TextAnnotator.tsx"],"sourcesContent":["import { ReactNode, useContext, useEffect, useRef } from 'react';\nimport { AnnotoriousContext, Filter } from '@annotorious/react';\nimport type { FormatAdapter } from '@annotorious/core';\nimport type { HighlightStyleExpression, TextAnnotation, TextAnnotatorOptions } from '@soomo/text-annotator';\nimport { createTextAnnotator } from '@soomo/text-annotator';\n\nimport '@soomo/text-annotator/dist/text-annotator.css';\n\nexport interface TextAnnotatorProps<E extends unknown> extends Omit<TextAnnotatorOptions<TextAnnotation, E>, 'adapter'> {\n\n children?: ReactNode | JSX.Element;\n\n adapter?: FormatAdapter<TextAnnotation, E> | ((container: HTMLElement) => FormatAdapter<TextAnnotation, E>) | null;\n\n filter?: Filter;\n\n style?: HighlightStyleExpression;\n\n className?: string;\n\n}\n\nexport const TextAnnotator = <E extends unknown>(props: TextAnnotatorProps<E>) => {\n\n const el = useRef<HTMLDivElement>(null);\n\n const { className, children, ...opts } = props;\n const { style, filter, user, annotatingEnabled, userSelectAction } = opts;\n\n const { anno, setAnno } = useContext(AnnotoriousContext);\n\n useEffect(() => {\n if (!setAnno) return;\n\n const adapter = typeof opts.adapter === 'function' ? opts.adapter(el.current) : opts.adapter;\n\n const anno = createTextAnnotator(el.current, { ...opts, adapter });\n setAnno(anno);\n\n return () => anno.destroy();\n }, [setAnno]);\n\n useEffect(() => anno?.setStyle(style), [anno, style]);\n\n useEffect(() => anno?.setFilter(filter), [anno, filter]);\n\n useEffect(() => anno?.setFilter(filter), [anno, filter]);\n\n useEffect(() => anno?.setUserSelectAction(userSelectAction), [anno, userSelectAction]);\n\n useEffect(() => anno?.setUser(user), [anno, user]);\n\n useEffect(() => anno?.setAnnotatingEnabled(annotatingEnabled), [anno, annotatingEnabled]);\n\n return (\n <div ref={el} className={className}>\n {children}\n </div>\n );\n\n};\n"],"names":["anno","jsx"],"mappings":";;;;;AAsBa,MAAA,gBAAgB,CAAoB,UAAiC;AAE1E,QAAA,KAAK,OAAuB,IAAI;AAEtC,QAAM,EAAE,WAAW,UAAU,GAAG,SAAS;AACzC,QAAM,EAAE,OAAO,QAAQ,MAAM,mBAAmB,iBAAqB,IAAA;AAErE,QAAM,EAAE,MAAM,QAAQ,IAAI,WAAW,kBAAkB;AAEvD,YAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAER,UAAA,UAAU,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,GAAG,OAAO,IAAI,KAAK;AAE/EA,UAAAA,QAAO,oBAAoB,GAAG,SAAS,EAAE,GAAG,MAAM,SAAS;AACjE,YAAQA,KAAI;AAEL,WAAA,MAAMA,MAAK;EAAQ,GACzB,CAAC,OAAO,CAAC;AAEF,YAAA,MAAM,6BAAM,SAAS,QAAQ,CAAC,MAAM,KAAK,CAAC;AAE1C,YAAA,MAAM,6BAAM,UAAU,SAAS,CAAC,MAAM,MAAM,CAAC;AAE7C,YAAA,MAAM,6BAAM,UAAU,SAAS,CAAC,MAAM,MAAM,CAAC;AAE7C,YAAA,MAAM,6BAAM,oBAAoB,mBAAmB,CAAC,MAAM,gBAAgB,CAAC;AAE3E,YAAA,MAAM,6BAAM,QAAQ,OAAO,CAAC,MAAM,IAAI,CAAC;AAEvC,YAAA,MAAM,6BAAM,qBAAqB,oBAAoB,CAAC,MAAM,iBAAiB,CAAC;AAExF,SACGC,kCAAAA,IAAA,OAAA,EAAI,KAAK,IAAI,WACX,SACH,CAAA;AAGJ;"}
|
|
@@ -1,13 +1,130 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { j as jsxRuntimeExports } from "./react-text-annotator.es8.js";
|
|
2
|
+
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
3
|
+
import { isMobile } from "./react-text-annotator.es11.js";
|
|
4
|
+
import { useFloating, useDismiss, useRole, useInteractions, FloatingPortal, FloatingFocusManager } from "./react-text-annotator.es12.js";
|
|
5
|
+
import { useAnnotator, useSelection } from "@annotorious/react";
|
|
6
|
+
import { denormalizeRectWithOffset, toDomRectList } from "@soomo/text-annotator";
|
|
7
|
+
import { useAnnouncePopupNavigation } from "./react-text-annotator.es4.js";
|
|
8
|
+
/* empty css */
|
|
9
|
+
import { offset, inline, flip, shift } from "./react-text-annotator.es14.js";
|
|
10
|
+
import { autoUpdate } from "./react-text-annotator.es15.js";
|
|
11
|
+
const TextAnnotatorPopup = (props) => {
|
|
12
|
+
var _a;
|
|
13
|
+
const { popup, ariaNavigationMessage } = props;
|
|
14
|
+
const r = useAnnotator();
|
|
15
|
+
const { selected, event } = useSelection();
|
|
16
|
+
const annotation = (_a = selected[0]) == null ? void 0 : _a.annotation;
|
|
17
|
+
const [isOpen, setOpen] = useState((selected == null ? void 0 : selected.length) > 0);
|
|
18
|
+
const handleClose = () => r == null ? void 0 : r.cancelSelected();
|
|
19
|
+
const [isFloatingFocused, setFloatingFocused] = useState(false);
|
|
20
|
+
const handleFloatingFocus = () => setFloatingFocused(true);
|
|
21
|
+
const handleFloatingBlur = () => setFloatingFocused(false);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!isOpen) handleFloatingBlur();
|
|
24
|
+
}, [isOpen, handleFloatingBlur]);
|
|
25
|
+
const { refs, floatingStyles, update, context } = useFloating({
|
|
26
|
+
placement: isMobile() ? "bottom" : "top",
|
|
27
|
+
open: isOpen,
|
|
28
|
+
onOpenChange: (open, _event, reason) => {
|
|
29
|
+
if (!open && (reason === "escape-key" || reason === "focus-out")) {
|
|
30
|
+
setOpen(open);
|
|
31
|
+
handleClose();
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
middleware: [
|
|
35
|
+
offset(10),
|
|
36
|
+
inline(),
|
|
37
|
+
flip(),
|
|
38
|
+
shift({ mainAxis: false, crossAxis: true, padding: 10 })
|
|
39
|
+
],
|
|
40
|
+
whileElementsMounted: autoUpdate
|
|
41
|
+
});
|
|
42
|
+
const dismiss = useDismiss(context);
|
|
43
|
+
const role = useRole(context, { role: "dialog" });
|
|
44
|
+
const { getFloatingProps } = useInteractions([dismiss, role]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
setOpen(
|
|
47
|
+
// Selected annotation exists and has a selector?
|
|
48
|
+
(annotation == null ? void 0 : annotation.target.selector) && // Selector not empty? (Annotations from plugins, general defensive programming)
|
|
49
|
+
annotation.target.selector.length > 0 && // Range not collapsed? (E.g. lazy loading PDFs. Note that this will have to
|
|
50
|
+
// change if we switch from ranges to pre-computed bounds!)
|
|
51
|
+
!annotation.target.selector[0].range.collapsed
|
|
52
|
+
);
|
|
53
|
+
}, [annotation]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!r) return;
|
|
56
|
+
if (isOpen && (annotation == null ? void 0 : annotation.id)) {
|
|
57
|
+
refs.setPositionReference({
|
|
58
|
+
getBoundingClientRect: () => denormalizeRectWithOffset(
|
|
59
|
+
r.state.store.getAnnotationBounds(annotation.id),
|
|
60
|
+
r.element.getBoundingClientRect()
|
|
61
|
+
),
|
|
62
|
+
getClientRects: () => {
|
|
63
|
+
const rects = r.state.store.getAnnotationRects(annotation.id);
|
|
64
|
+
const denormalizedRects = rects.map(
|
|
65
|
+
(rect) => denormalizeRectWithOffset(rect, r.element.getBoundingClientRect())
|
|
66
|
+
);
|
|
67
|
+
return toDomRectList(denormalizedRects);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
refs.setPositionReference(null);
|
|
72
|
+
}
|
|
73
|
+
}, [isOpen, annotation == null ? void 0 : annotation.id, annotation == null ? void 0 : annotation.target, r]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const config = { attributes: true, childList: true, subtree: true };
|
|
76
|
+
const mutationObserver = new MutationObserver(() => update());
|
|
77
|
+
mutationObserver.observe(document.body, config);
|
|
78
|
+
window.document.addEventListener("scroll", update, true);
|
|
79
|
+
return () => {
|
|
80
|
+
mutationObserver.disconnect();
|
|
81
|
+
window.document.removeEventListener("scroll", update, true);
|
|
82
|
+
};
|
|
83
|
+
}, [update]);
|
|
84
|
+
const initialFocus = useMemo(() => {
|
|
85
|
+
return (event == null ? void 0 : event.type) === "keyup" || (event == null ? void 0 : event.type) === "contextmenu" || isMobile() ? -1 : 0;
|
|
86
|
+
}, [event]);
|
|
87
|
+
useAnnouncePopupNavigation({
|
|
88
|
+
disabled: isFloatingFocused,
|
|
89
|
+
floatingOpen: isOpen,
|
|
90
|
+
message: ariaNavigationMessage
|
|
91
|
+
});
|
|
92
|
+
const getStopEventsPropagationProps = useCallback(
|
|
93
|
+
() => ({ onPointerUp: (event2) => event2.stopPropagation() }),
|
|
94
|
+
[]
|
|
95
|
+
);
|
|
96
|
+
return isOpen && annotation ? /* @__PURE__ */ jsxRuntimeExports.jsx(FloatingPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
97
|
+
FloatingFocusManager,
|
|
98
|
+
{
|
|
99
|
+
context,
|
|
100
|
+
modal: false,
|
|
101
|
+
closeOnFocusOut: true,
|
|
102
|
+
returnFocus: false,
|
|
103
|
+
initialFocus,
|
|
104
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
105
|
+
"div",
|
|
106
|
+
{
|
|
107
|
+
className: "a9s-popup r6o-popup annotation-popup r6o-text-popup not-annotatable",
|
|
108
|
+
ref: refs.setFloating,
|
|
109
|
+
style: floatingStyles,
|
|
110
|
+
onFocus: handleFloatingFocus,
|
|
111
|
+
onBlur: handleFloatingBlur,
|
|
112
|
+
...getFloatingProps(),
|
|
113
|
+
...getStopEventsPropagationProps(),
|
|
114
|
+
children: [
|
|
115
|
+
popup({
|
|
116
|
+
annotation: selected[0].annotation,
|
|
117
|
+
editable: selected[0].editable,
|
|
118
|
+
event
|
|
119
|
+
}),
|
|
120
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "r6o-popup-sr-only", "aria-live": "assertive", onClick: handleClose, children: props.ariaCloseWarning || "Click or leave this dialog to close it." })
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
) }) : null;
|
|
126
|
+
};
|
|
10
127
|
export {
|
|
11
|
-
|
|
128
|
+
TextAnnotatorPopup
|
|
12
129
|
};
|
|
13
130
|
//# sourceMappingURL=react-text-annotator.es6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-text-annotator.es6.js","sources":["
|
|
1
|
+
{"version":3,"file":"react-text-annotator.es6.js","sources":["../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx"],"sourcesContent":["import { FC, PointerEvent, ReactNode, useCallback, useEffect, useMemo, useState } from 'react';\nimport { isMobile } from './isMobile';\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingPortal,\n inline,\n offset,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n useRole\n} from '@floating-ui/react';\n\nimport { useAnnotator, useSelection } from '@annotorious/react';\nimport {\n denormalizeRectWithOffset,\n toDomRectList,\n type TextAnnotation,\n type TextAnnotator,\n} from '@soomo/text-annotator';\n\nimport { useAnnouncePopupNavigation } from '../hooks';\nimport './TextAnnotatorPopup.css';\n\ninterface TextAnnotationPopupProps {\n\n ariaNavigationMessage?: string;\n\n ariaCloseWarning?: string;\n\n popup(props: TextAnnotationPopupContentProps): ReactNode;\n\n}\n\nexport interface TextAnnotationPopupContentProps {\n\n annotation: TextAnnotation;\n\n editable?: boolean;\n\n event?: PointerEvent;\n\n}\n\nexport const TextAnnotatorPopup: FC<TextAnnotationPopupProps> = (props) => {\n\n const { popup, ariaNavigationMessage } = props;\n\n const r = useAnnotator<TextAnnotator>();\n\n const { selected, event } = useSelection<TextAnnotation>();\n\n const annotation = selected[0]?.annotation;\n\n const [isOpen, setOpen] = useState(selected?.length > 0);\n const handleClose = () => r?.cancelSelected();\n\n const [isFloatingFocused, setFloatingFocused] = useState(false);\n const handleFloatingFocus = () => setFloatingFocused(true);\n const handleFloatingBlur = () => setFloatingFocused(false);\n useEffect(() => {\n if (!isOpen) handleFloatingBlur();\n }, [isOpen, handleFloatingBlur]);\n\n const { refs, floatingStyles, update, context } = useFloating({\n placement: isMobile() ? 'bottom' : 'top',\n open: isOpen,\n onOpenChange: (open, _event, reason) => {\n if (!open && (reason === 'escape-key' || reason === 'focus-out')) {\n setOpen(open);\n handleClose();\n }\n },\n middleware: [\n offset(10),\n inline(),\n flip(),\n shift({ mainAxis: false, crossAxis: true, padding: 10 })\n ],\n whileElementsMounted: autoUpdate\n });\n\n const dismiss = useDismiss(context);\n\n const role = useRole(context, { role: 'dialog' });\n\n const { getFloatingProps } = useInteractions([dismiss, role]);\n\n useEffect(() => {\n setOpen(\n // Selected annotation exists and has a selector?\n annotation?.target.selector &&\n // Selector not empty? (Annotations from plugins, general defensive programming)\n annotation.target.selector.length > 0 &&\n // Range not collapsed? (E.g. lazy loading PDFs. Note that this will have to\n // change if we switch from ranges to pre-computed bounds!)\n !annotation.target.selector[0].range.collapsed\n );\n }, [annotation]);\n\n useEffect(() => {\n if (!r) return;\n\n if (isOpen && annotation?.id) {\n refs.setPositionReference({\n getBoundingClientRect: () => denormalizeRectWithOffset(\n r.state.store.getAnnotationBounds(annotation.id),\n r.element.getBoundingClientRect()\n ),\n getClientRects: () => {\n const rects = r.state.store.getAnnotationRects(annotation.id);\n const denormalizedRects = rects.map(\n rect => denormalizeRectWithOffset(rect, r.element.getBoundingClientRect())\n );\n return toDomRectList(denormalizedRects);\n }\n });\n } else {\n refs.setPositionReference(null);\n }\n }, [isOpen, annotation?.id, annotation?.target, r]);\n\n useEffect(() => {\n const config: MutationObserverInit = { attributes: true, childList: true, subtree: true };\n\n const mutationObserver = new MutationObserver(() => update());\n mutationObserver.observe(document.body, config);\n\n window.document.addEventListener('scroll', update, true);\n\n return () => {\n mutationObserver.disconnect();\n window.document.removeEventListener('scroll', update, true);\n };\n }, [update]);\n\n // Don't shift focus to the floating element if selected via keyboard or on mobile.\n const initialFocus = useMemo(() => {\n return (event?.type === 'keyup' || event?.type === 'contextmenu' || isMobile()) ? -1 : 0;\n }, [event]);\n\n /**\n * Announce the navigation hint only on the keyboard selection,\n * because the focus isn't shifted to the popup automatically then\n */\n useAnnouncePopupNavigation({\n disabled: isFloatingFocused,\n floatingOpen: isOpen,\n message: ariaNavigationMessage,\n });\n\n // Prevent text-annotator from handling the irrelevant events triggered from the popup\n const getStopEventsPropagationProps = useCallback(\n () => ({ onPointerUp: (event: PointerEvent<HTMLDivElement>) => event.stopPropagation() }),\n []\n );\n\n return isOpen && annotation ? (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n modal={false}\n closeOnFocusOut={true}\n returnFocus={false}\n initialFocus={initialFocus}>\n <div\n className=\"a9s-popup r6o-popup annotation-popup r6o-text-popup not-annotatable\"\n ref={refs.setFloating}\n style={floatingStyles}\n onFocus={handleFloatingFocus}\n onBlur={handleFloatingBlur}\n {...getFloatingProps()}\n {...getStopEventsPropagationProps()}>\n {popup({\n annotation: selected[0].annotation,\n editable: selected[0].editable,\n event\n })}\n <button className=\"r6o-popup-sr-only\" aria-live=\"assertive\" onClick={handleClose}>\n {props.ariaCloseWarning || 'Click or leave this dialog to close it.'}\n </button>\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n ) : null;\n\n}\n"],"names":["event","jsx","jsxs"],"mappings":"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"}
|