@soomo/react-text-annotator 3.0.0-staging.37 → 3.0.0-staging.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/{TextAnnotatorPopup.d.ts → TextAnnotatorPopup/TextAnnotatorPopup.d.ts} +3 -2
  2. package/dist/TextAnnotatorPopup/TextAnnotatorPopup.d.ts.map +1 -0
  3. package/dist/TextAnnotatorPopup/index.d.ts +2 -0
  4. package/dist/TextAnnotatorPopup/index.d.ts.map +1 -0
  5. package/dist/hooks/index.d.ts +3 -0
  6. package/dist/hooks/index.d.ts.map +1 -0
  7. package/dist/hooks/useAnnouncePopupNavigation.d.ts +8 -0
  8. package/dist/hooks/useAnnouncePopupNavigation.d.ts.map +1 -0
  9. package/dist/hooks/useRestoreSelectionCaret.d.ts +13 -0
  10. package/dist/hooks/useRestoreSelectionCaret.d.ts.map +1 -0
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/react-text-annotator.css +31 -1
  14. package/dist/react-text-annotator.es.js +8 -4
  15. package/dist/react-text-annotator.es.js.map +1 -1
  16. package/dist/react-text-annotator.es11.js +445 -527
  17. package/dist/react-text-annotator.es11.js.map +1 -1
  18. package/dist/react-text-annotator.es12.js +60 -483
  19. package/dist/react-text-annotator.es12.js.map +1 -1
  20. package/dist/react-text-annotator.es13.js +45 -2
  21. package/dist/react-text-annotator.es13.js.map +1 -1
  22. package/dist/react-text-annotator.es14.js +1450 -30
  23. package/dist/react-text-annotator.es14.js.map +1 -1
  24. package/dist/react-text-annotator.es16.js +227 -37
  25. package/dist/react-text-annotator.es16.js.map +1 -1
  26. package/dist/react-text-annotator.es17.js +537 -115
  27. package/dist/react-text-annotator.es17.js.map +1 -1
  28. package/dist/react-text-annotator.es18.js +2 -2
  29. package/dist/react-text-annotator.es19.js +31 -2
  30. package/dist/react-text-annotator.es19.js.map +1 -1
  31. package/dist/react-text-annotator.es2.js +2 -2
  32. package/dist/react-text-annotator.es20.js +893 -109
  33. package/dist/react-text-annotator.es20.js.map +1 -1
  34. package/dist/react-text-annotator.es21.js +2 -309
  35. package/dist/react-text-annotator.es21.js.map +1 -1
  36. package/dist/react-text-annotator.es22.js +2 -58
  37. package/dist/react-text-annotator.es22.js.map +1 -1
  38. package/dist/react-text-annotator.es23.js +113 -19
  39. package/dist/react-text-annotator.es23.js.map +1 -1
  40. package/dist/react-text-annotator.es24.js +290 -130
  41. package/dist/react-text-annotator.es24.js.map +1 -1
  42. package/dist/react-text-annotator.es25.js +43 -545
  43. package/dist/react-text-annotator.es25.js.map +1 -1
  44. package/dist/react-text-annotator.es26.js +23 -0
  45. package/dist/react-text-annotator.es26.js.map +1 -0
  46. package/dist/react-text-annotator.es27.js +130 -0
  47. package/dist/react-text-annotator.es27.js.map +1 -0
  48. package/dist/react-text-annotator.es28.js +155 -0
  49. package/dist/react-text-annotator.es28.js.map +1 -0
  50. package/dist/react-text-annotator.es29.js +314 -0
  51. package/dist/react-text-annotator.es29.js.map +1 -0
  52. package/dist/react-text-annotator.es3.js +2 -2
  53. package/dist/react-text-annotator.es30.js +152 -0
  54. package/dist/react-text-annotator.es30.js.map +1 -0
  55. package/dist/react-text-annotator.es31.js +563 -0
  56. package/dist/react-text-annotator.es31.js.map +1 -0
  57. package/dist/react-text-annotator.es4.js +30 -23
  58. package/dist/react-text-annotator.es4.js.map +1 -1
  59. package/dist/react-text-annotator.es5.js +36 -78
  60. package/dist/react-text-annotator.es5.js.map +1 -1
  61. package/dist/react-text-annotator.es6.js +24 -178
  62. package/dist/react-text-annotator.es6.js.map +1 -1
  63. package/dist/react-text-annotator.es7.js +126 -10
  64. package/dist/react-text-annotator.es7.js.map +1 -1
  65. package/dist/react-text-annotator.es8.js +182 -0
  66. package/dist/react-text-annotator.es8.js.map +1 -0
  67. package/dist/react-text-annotator.es9.js +10 -670
  68. package/dist/react-text-annotator.es9.js.map +1 -1
  69. package/package.json +5 -3
  70. package/dist/TextAnnotatorPopup.d.ts.map +0 -1
  71. package/dist/react-text-annotator.es10.js +0 -244
  72. package/dist/react-text-annotator.es10.js.map +0 -1
  73. package/dist/react-text-annotator.es15.js +0 -901
  74. package/dist/react-text-annotator.es15.js.map +0 -1
@@ -1,28 +1,35 @@
1
- import { j as jsxRuntimeExports } from "./react-text-annotator.es7.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 { annotatingEnabled, style, filter, userSelectAction, user } = opts;
10
- const { anno, setAnno } = useContext(AnnotoriousContext);
1
+ import { useRef, useEffect } from "react";
2
+ import { useSelection } from "@annotorious/react";
3
+ const useRestoreSelectionCaret = (args) => {
4
+ var _a;
5
+ const { floatingOpen } = args;
6
+ const { selected } = useSelection();
7
+ const annotation = (_a = selected[0]) == null ? void 0 : _a.annotation;
8
+ const selectionRangeRef = useRef(null);
11
9
  useEffect(() => {
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.setUserSelectAction(userSelectAction), [anno, userSelectAction]);
21
- useEffect(() => anno == null ? void 0 : anno.setUser(user), [anno, user]);
22
- useEffect(() => anno == null ? void 0 : anno.setAnnotatingEnabled(annotatingEnabled), [anno, annotatingEnabled]);
23
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: el, className, children });
10
+ if (!floatingOpen || !annotation) return;
11
+ const sel = document.getSelection();
12
+ if (sel) {
13
+ selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
14
+ }
15
+ }, [floatingOpen, annotation]);
16
+ useEffect(() => {
17
+ if (floatingOpen) return;
18
+ const { current: selectionRange } = selectionRangeRef;
19
+ if (!selectionRange) return;
20
+ const { startContainer, startOffset } = selectionRange;
21
+ setTimeout(() => {
22
+ const sel = document.getSelection();
23
+ if (sel && sel.isCollapsed && sel.anchorNode === document.body) {
24
+ sel.removeAllRanges();
25
+ sel.setPosition(startContainer, startOffset);
26
+ const startContainerElement = startContainer instanceof HTMLElement ? startContainer : startContainer.parentElement;
27
+ startContainerElement.focus({ preventScroll: true });
28
+ }
29
+ });
30
+ }, [floatingOpen]);
24
31
  };
25
32
  export {
26
- TextAnnotator
33
+ useRestoreSelectionCaret
27
34
  };
28
35
  //# sourceMappingURL=react-text-annotator.es4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-text-annotator.es4.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\n\nexport interface TextAnnotatorProps<E extends unknown> extends Omit<TextAnnotatorOptions<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 { annotatingEnabled, style, filter, userSelectAction, user } = 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?.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":";;;;;AAuBa,MAAA,gBAAgB,CAAoB,UAAiC;AAE1E,QAAA,KAAK,OAAuB,IAAI;AAEtC,QAAM,EAAE,WAAW,UAAU,GAAG,SAAS;AACzC,QAAM,EAAE,mBAAmB,OAAO,QAAQ,kBAAkB,KAAS,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,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
+ {"version":3,"file":"react-text-annotator.es4.js","sources":["../src/hooks/useRestoreSelectionCaret.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\n\nimport { useSelection } from '@annotorious/react';\nimport type { TextAnnotation } from '@recogito/text-annotator';\n\n/**\n * Restores the caret position after the floating element gets closed\n * and the selection is lost and moved to the `body`.\n * The caret is placed at the start of the previous selection range.\n *\n * However, when the floating element is dismissed with intentional\n * caret repositioning via the mouse click or arrow key navigation ->\n * we shouldn't restore its position to the previous selection.\n */\nexport const useRestoreSelectionCaret = (args: { floatingOpen: boolean }) => {\n const { floatingOpen } = args;\n\n const { selected } = useSelection<TextAnnotation>();\n const annotation = selected[0]?.annotation;\n\n const selectionRangeRef = useRef<Range | null>(null);\n\n useEffect(() => {\n if (!floatingOpen || !annotation) return;\n\n const sel = document.getSelection();\n if (sel) {\n selectionRangeRef.current = sel.getRangeAt(0).cloneRange();\n }\n }, [floatingOpen, annotation]);\n\n useEffect(() => {\n if (floatingOpen) return;\n\n const { current: selectionRange } = selectionRangeRef;\n if (!selectionRange) return;\n\n const { startContainer, startOffset } = selectionRange;\n\n setTimeout(() => {\n const sel = document.getSelection();\n if (sel && sel.isCollapsed && sel.anchorNode === document.body) {\n sel.removeAllRanges();\n sel.setPosition(startContainer, startOffset);\n\n const startContainerElement = startContainer instanceof HTMLElement\n ? startContainer\n : startContainer.parentElement;\n startContainerElement.focus({ preventScroll: true });\n }\n });\n }, [floatingOpen]);\n};\n"],"names":[],"mappings":";;AAca,MAAA,2BAA2B,CAAC,SAAoC;;AACrE,QAAA,EAAE,aAAiB,IAAA;AAEnB,QAAA,EAAE,aAAa;AACf,QAAA,cAAa,cAAS,CAAC,MAAV,mBAAa;AAE1B,QAAA,oBAAoB,OAAqB,IAAI;AAEnD,YAAU,MAAM;AACV,QAAA,CAAC,gBAAgB,CAAC,WAAY;AAE5B,UAAA,MAAM,SAAS;AACrB,QAAI,KAAK;AACP,wBAAkB,UAAU,IAAI,WAAW,CAAC,EAAE;IAChD;AAAA,EAAA,GACC,CAAC,cAAc,UAAU,CAAC;AAE7B,YAAU,MAAM;AACd,QAAI,aAAc;AAEZ,UAAA,EAAE,SAAS,eAAmB,IAAA;AACpC,QAAI,CAAC,eAAgB;AAEf,UAAA,EAAE,gBAAgB,YAAgB,IAAA;AAExC,eAAW,MAAM;AACT,YAAA,MAAM,SAAS;AACrB,UAAI,OAAO,IAAI,eAAe,IAAI,eAAe,SAAS,MAAM;AAC9D,YAAI,gBAAgB;AAChB,YAAA,YAAY,gBAAgB,WAAW;AAE3C,cAAM,wBAAwB,0BAA0B,cACpD,iBACA,eAAe;AACnB,8BAAsB,MAAM,EAAE,eAAe,KAAM,CAAA;AAAA,MACrD;AAAA,IAAA,CACD;AAAA,EAAA,GACA,CAAC,YAAY,CAAC;AACnB;"}
@@ -1,85 +1,43 @@
1
- import { j as jsxRuntimeExports } from "./react-text-annotator.es7.js";
2
- import { useState, useEffect, useCallback } from "react";
3
- import { useAnnotator, useSelection } from "@annotorious/react";
4
- import { denormalizeRectWithOffset, toDomRectList } from "@soomo/text-annotator";
5
- import { useFloating, useDismiss, useRole, useInteractions } from "./react-text-annotator.es9.js";
6
- import { offset, inline, flip, shift } from "./react-text-annotator.es10.js";
7
- import { autoUpdate } from "./react-text-annotator.es11.js";
8
- const TextAnnotatorPopup = (props) => {
9
- var _a;
10
- const r = useAnnotator();
11
- const { selected, event } = useSelection();
12
- const annotation = (_a = selected[0]) == null ? void 0 : _a.annotation;
13
- const [isOpen, setOpen] = useState((selected == null ? void 0 : selected.length) > 0);
14
- const { refs, floatingStyles, update, context } = useFloating({
15
- placement: "top",
16
- open: isOpen,
17
- onOpenChange: (open, _event, reason) => {
18
- setOpen(open);
19
- if (!open && reason === "escape-key") {
20
- r == null ? void 0 : r.cancelSelected();
21
- }
22
- },
23
- middleware: [
24
- offset(10),
25
- inline(),
26
- flip(),
27
- shift({ mainAxis: false, crossAxis: true, padding: 10 })
28
- ],
29
- whileElementsMounted: autoUpdate
30
- });
31
- const dismiss = useDismiss(context);
32
- const role = useRole(context, { role: "tooltip" });
33
- const { getFloatingProps } = useInteractions([dismiss, role]);
34
- const selectedKey = selected.map((a) => a.annotation.id).join("-");
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.es12.js";
4
+ import { exhaustiveUniqueRandom } from "./react-text-annotator.es13.js";
5
+ const useAnnouncePopupNavigation = (args) => {
6
+ const {
7
+ message = "Press Tab to move to Notes Dialog",
8
+ floatingOpen,
9
+ disabled = false
10
+ } = args;
11
+ const store = useAnnotationStore();
12
+ const { event } = useSelection();
13
+ const uniqueRandom = useCallback(exhaustiveUniqueRandom(1, 1e4), []);
14
+ useLayoutEffect(() => {
15
+ if (!message) return;
16
+ $319e236875307eab$export$a9b970dcc4ae71a9("", "polite");
17
+ return () => $319e236875307eab$export$d8686216b8b81b2f();
18
+ }, [message]);
19
+ const announcementSeed = useMemo(() => floatingOpen ? uniqueRandom() : 0, [floatingOpen]);
20
+ const announcePopupNavigation = useCallback(() => {
21
+ const uniqueSpaces = Array.from({ length: announcementSeed }).map(() => " ").join("");
22
+ $319e236875307eab$export$a9b970dcc4ae71a9(`${message} ${uniqueSpaces}`, "polite");
23
+ }, [message, announcementSeed]);
24
+ const idleTimeoutMs = 700;
25
+ const idleTimeoutRef = useRef(null);
35
26
  useEffect(() => {
36
- if (event) {
37
- setOpen(selected.length > 0 && (event.type === "pointerup" || event.type === "keyup"));
38
- }
39
- }, [event, selectedKey]);
40
- useEffect(() => {
41
- if (!isOpen || !(annotation == null ? void 0 : annotation.id) || !r) return;
42
- refs.setPositionReference({
43
- getBoundingClientRect: () => denormalizeRectWithOffset(
44
- r.state.store.getAnnotationBounds(annotation.id),
45
- r.element.getBoundingClientRect()
46
- ),
47
- getClientRects: () => {
48
- const rects = r.state.store.getAnnotationRects(annotation.id);
49
- const denormalizedRects = rects.map(
50
- (rect) => denormalizeRectWithOffset(rect, r.element.getBoundingClientRect())
51
- );
52
- return toDomRectList(denormalizedRects);
53
- }
54
- });
55
- }, [isOpen, annotation == null ? void 0 : annotation.id, r]);
56
- const getStopEventsPropagationProps = useCallback(
57
- () => ({ onPointerUp: (event2) => event2.stopPropagation() }),
58
- []
59
- );
60
- useEffect(() => {
61
- const config = { attributes: true, childList: true, subtree: true };
62
- const mutationObserver = new MutationObserver(() => update());
63
- mutationObserver.observe(document.body, config);
64
- window.document.addEventListener("scroll", update, true);
27
+ if (disabled || !floatingOpen || !message) return;
28
+ const scheduleIdleAnnouncement = () => {
29
+ clearTimeout(idleTimeoutRef.current);
30
+ idleTimeoutRef.current = setTimeout(announcePopupNavigation, idleTimeoutMs);
31
+ };
32
+ scheduleIdleAnnouncement();
33
+ store.observe(scheduleIdleAnnouncement, { origin: Origin.LOCAL });
65
34
  return () => {
66
- mutationObserver.disconnect();
67
- window.document.removeEventListener("scroll", update, true);
35
+ clearTimeout(idleTimeoutRef.current);
36
+ store.unobserve(scheduleIdleAnnouncement);
68
37
  };
69
- }, [update]);
70
- return isOpen && selected.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
71
- "div",
72
- {
73
- className: "annotation-popup text-annotation-popup not-annotatable",
74
- ref: refs.setFloating,
75
- style: floatingStyles,
76
- ...getFloatingProps(),
77
- ...getStopEventsPropagationProps(),
78
- children: props.popup({ selected })
79
- }
80
- ) : null;
38
+ }, [floatingOpen, event == null ? void 0 : event.type, message, announcePopupNavigation, store]);
81
39
  };
82
40
  export {
83
- TextAnnotatorPopup
41
+ useAnnouncePopupNavigation
84
42
  };
85
43
  //# sourceMappingURL=react-text-annotator.es5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-text-annotator.es5.js","sources":["../src/TextAnnotatorPopup.tsx"],"sourcesContent":["import { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react';\nimport { useAnnotator, useSelection } from '@annotorious/react';\nimport { toDomRectList, denormalizeRectWithOffset, type TextAnnotation, type TextAnnotator } from '@soomo/text-annotator';\nimport {\n autoUpdate,\n inline,\n offset,\n flip,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n useRole\n} from '@floating-ui/react';\n\ninterface TextAnnotationPopupProps {\n\n popup(props: TextAnnotatorPopupProps): ReactNode;\n\n}\n\nexport interface TextAnnotatorPopupProps {\n\n selected: { annotation: TextAnnotation, editable?: boolean }[];\n\n}\n\nexport const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => {\n\n const r = useAnnotator<TextAnnotator>();\n\n const { selected, event } = useSelection<TextAnnotation>();\n const annotation = selected[0]?.annotation;\n\n const [isOpen, setOpen] = useState(selected?.length > 0);\n\n const { refs, floatingStyles, update, context } = useFloating({\n placement: 'top',\n open: isOpen,\n onOpenChange: (open, _event, reason) => {\n setOpen(open);\n if (!open && reason === 'escape-key') {\n r?.cancelSelected();\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: 'tooltip' });\n\n const { getFloatingProps } = useInteractions([dismiss, role]);\n\n const selectedKey = selected.map(a => a.annotation.id).join('-');\n\n useEffect(() => {\n // Ignore all selection changes except those accompanied by a user event.\n if (event) {\n setOpen(selected.length > 0 && (event.type === 'pointerup' || event.type === 'keyup'));\n }\n }, [event, selectedKey]);\n\n useEffect(() => {\n if (!isOpen || !annotation?.id || !r) return;\n\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 }, [isOpen, annotation?.id, r]);\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 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 return isOpen && selected.length > 0 ? (\n <div\n className=\"annotation-popup text-annotation-popup not-annotatable\"\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n {...getStopEventsPropagationProps()}>\n {props.popup({ selected })}\n </div>\n ) : null;\n\n}\n"],"names":["event","jsx"],"mappings":";;;;;;;AA2Ba,MAAA,qBAAqB,CAAC,UAAoC;;AAErE,QAAM,IAAI;AAEV,QAAM,EAAE,UAAU,MAAM,IAAI,aAA6B;AACnD,QAAA,cAAa,cAAS,CAAC,MAAV,mBAAa;AAEhC,QAAM,CAAC,QAAQ,OAAO,IAAI,UAAS,qCAAU,UAAS,CAAC;AAEvD,QAAM,EAAE,MAAM,gBAAgB,QAAQ,QAAA,IAAY,YAAY;AAAA,IAC5D,WAAW;AAAA,IACX,MAAM;AAAA,IACN,cAAc,CAAC,MAAM,QAAQ,WAAW;AACtC,cAAQ,IAAI;AACR,UAAA,CAAC,QAAQ,WAAW,cAAc;AACpC,+BAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,OAAO,EAAE;AAAA,MACT,OAAO;AAAA,MACP,KAAK;AAAA,MACL,MAAM,EAAE,UAAU,OAAO,WAAW,MAAM,SAAS,IAAI;AAAA,IACzD;AAAA,IACA,sBAAsB;AAAA,EAAA,CACvB;AAEK,QAAA,UAAU,WAAW,OAAO;AAElC,QAAM,OAAO,QAAQ,SAAS,EAAE,MAAM,WAAW;AAEjD,QAAM,EAAE,iBAAiB,IAAI,gBAAgB,CAAC,SAAS,IAAI,CAAC;AAEtD,QAAA,cAAc,SAAS,IAAI,CAAA,MAAK,EAAE,WAAW,EAAE,EAAE,KAAK,GAAG;AAE/D,YAAU,MAAM;AAEd,QAAI,OAAO;AACD,cAAA,SAAS,SAAS,MAAM,MAAM,SAAS,eAAe,MAAM,SAAS,QAAQ;AAAA,IACvF;AAAA,EAAA,GACC,CAAC,OAAO,WAAW,CAAC;AAEvB,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,EAAC,yCAAY,OAAM,CAAC,EAAG;AAEtC,SAAK,qBAAqB;AAAA,MACxB,uBAAuB,MAAM;AAAA,QAC3B,EAAE,MAAM,MAAM,oBAAoB,WAAW,EAAE;AAAA,QAC/C,EAAE,QAAQ,sBAAsB;AAAA,MAClC;AAAA,MACA,gBAAgB,MAAM;AACpB,cAAM,QAAQ,EAAE,MAAM,MAAM,mBAAmB,WAAW,EAAE;AAC5D,cAAM,oBAAoB,MAAM;AAAA,UAC9B,UAAQ,0BAA0B,MAAM,EAAE,QAAQ,uBAAuB;AAAA,QAAA;AAE3E,eAAO,cAAc,iBAAiB;AAAA,MACxC;AAAA,IAAA,CACD;AAAA,KACA,CAAC,QAAQ,yCAAY,IAAI,CAAC,CAAC;AAG9B,QAAM,gCAAgC;AAAA,IACpC,OAAO,EAAE,aAAa,CAACA,WAAwCA,OAAM,gBAAkB,EAAA;AAAA,IACvF,CAAC;AAAA,EAAA;AAGH,YAAU,MAAM;AACd,UAAM,SAA+B,EAAE,YAAY,MAAM,WAAW,MAAM,SAAS;AAEnF,UAAM,mBAAmB,IAAI,iBAAiB,MAAM,OAAQ,CAAA;AAC3C,qBAAA,QAAQ,SAAS,MAAM,MAAM;AAE9C,WAAO,SAAS,iBAAiB,UAAU,QAAQ,IAAI;AAEvD,WAAO,MAAM;AACX,uBAAiB,WAAW;AAC5B,aAAO,SAAS,oBAAoB,UAAU,QAAQ,IAAI;AAAA,IAAA;AAAA,EAC5D,GACC,CAAC,MAAM,CAAC;AAEJ,SAAA,UAAU,SAAS,SAAS,IACjCC,kCAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,KAAK,KAAK;AAAA,MACV,OAAO;AAAA,MACN,GAAG,iBAAiB;AAAA,MACpB,GAAG,8BAA8B;AAAA,MACjC,UAAM,MAAA,MAAM,EAAE,SAAA,CAAU;AAAA,IAAA;AAAA,EAEzB,IAAA;AAEN;"}
1
+ {"version":3,"file":"react-text-annotator.es5.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 floatingOpen: boolean;\n disabled?: boolean;\n}\n\nexport const useAnnouncePopupNavigation = (args: AnnouncePopupOpeningArgs) => {\n const {\n message = 'Press Tab to move to Notes Dialog',\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 (!message) return;\n\n announce('', 'polite');\n return () => destroyAnnouncer();\n }, [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 idleTimeoutMs = 700;\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, idleTimeoutMs);\n };\n\n scheduleIdleAnnouncement();\n store.observe(scheduleIdleAnnouncement, { origin: Origin.LOCAL });\n\n return () => {\n clearTimeout(idleTimeoutRef.current);\n store.unobserve(scheduleIdleAnnouncement);\n };\n }, [floatingOpen, event?.type, message, announcePopupNavigation, store]);\n};\n"],"names":["announce","destroyAnnouncer"],"mappings":";;;;AAaa,MAAA,6BAA6B,CAAC,SAAmC;AACtE,QAAA;AAAA,IACJ,UAAU;AAAA,IACV;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;AACpB,QAAI,CAAC,QAAS;AAEdA,8CAAS,IAAI,QAAQ;AACrB,WAAO,MAAMC,0CAAiB;AAAA,EAAA,GAC7B,CAAC,OAAO,CAAC;AAMN,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;AAE9B,QAAM,gBAAgB;AAChB,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,aAAa;AAAA,IAAA;AAGnD;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,cAAc,+BAAO,MAAM,SAAS,yBAAyB,KAAK,CAAC;AACzE;"}
@@ -1,182 +1,28 @@
1
- const Yt = "not-annotatable", D = `.${Yt}`, pt = (t) => {
2
- const e = t.cloneContents();
3
- return e.querySelectorAll(D).forEach((n) => n.remove()), e;
4
- }, oe = (t, e, n = 10, o) => {
5
- const r = e, i = document.createRange();
6
- i.setStart(r, 0), i.setEnd(t.startContainer, t.startOffset);
7
- const s = pt(i).textContent, a = document.createRange();
8
- a.setStart(t.endContainer, t.endOffset), r === document.body ? a.setEnd(r, r.childNodes.length) : a.setEndAfter(r);
9
- const u = pt(a).textContent;
10
- return {
11
- prefix: s.substring(s.length - n),
12
- suffix: u.substring(0, n)
13
- };
14
- };
15
- var U = [];
16
- for (var lt = 0; lt < 256; ++lt)
17
- U.push((lt + 256).toString(16).slice(1));
18
- function Re(t, e = 0) {
19
- return (U[t[e + 0]] + U[t[e + 1]] + U[t[e + 2]] + U[t[e + 3]] + "-" + U[t[e + 4]] + U[t[e + 5]] + "-" + U[t[e + 6]] + U[t[e + 7]] + "-" + U[t[e + 8]] + U[t[e + 9]] + "-" + U[t[e + 10]] + U[t[e + 11]] + U[t[e + 12]] + U[t[e + 13]] + U[t[e + 14]] + U[t[e + 15]]).toLowerCase();
20
- }
21
- var Z, Ne = new Uint8Array(16);
22
- function Me() {
23
- if (!Z && (Z = typeof crypto < "u" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto), !Z))
24
- throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
25
- return Z(Ne);
26
- }
27
- var Oe = typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
28
- const Mt = {
29
- randomUUID: Oe
30
- };
31
- function Ht(t, e, n) {
32
- if (Mt.randomUUID && !e && !t)
33
- return Mt.randomUUID();
34
- t = t || {};
35
- var o = t.random || (t.rng || Me)();
36
- return o[6] = o[6] & 15 | 64, o[8] = o[8] & 63 | 128, Re(o);
37
- }
38
- var V = [];
39
- for (var ht = 0; ht < 256; ++ht)
40
- V.push((ht + 256).toString(16).slice(1));
41
- typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
42
- const on = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
43
- let cn = (t = 21) => {
44
- let e = "", n = crypto.getRandomValues(new Uint8Array(t));
45
- for (; t--; )
46
- e += on[n[t] & 63];
47
- return e;
48
- };
49
- const dn = (t) => {
50
- const e = JSON.stringify(t);
51
- let n = 0;
52
- for (let o = 0, r = e.length; o < r; o++) {
53
- let i = e.charCodeAt(o);
54
- n = (n << 5) - n + i, n |= 0;
55
- }
56
- return `${n}`;
57
- }, Ft = (t) => t ? typeof t == "object" ? { ...t } : t : void 0, un = (t, e) => (Array.isArray(t) ? t : [t]).map((n) => {
58
- const { id: o, type: r, purpose: i, value: s, created: a, modified: u, creator: f, ...g } = n;
59
- return {
60
- id: o || `temp-${dn(n)}`,
61
- annotation: e,
62
- type: r,
63
- purpose: i,
64
- value: s,
65
- creator: Ft(f),
66
- created: a ? new Date(a) : void 0,
67
- updated: u ? new Date(u) : void 0,
68
- ...g
69
- };
70
- }), hn = (t) => t.map((e) => {
71
- var n;
72
- const { annotation: o, created: r, updated: i, ...s } = e, a = {
73
- ...s,
74
- created: r == null ? void 0 : r.toISOString(),
75
- modified: i == null ? void 0 : i.toISOString()
76
- };
77
- return (n = a.id) != null && n.startsWith("temp-") && delete a.id, a;
78
- });
79
- cn();
80
- const Vn = (t, e) => ({
81
- parse: (n) => pn(n),
82
- serialize: (n) => mn(n, t, e)
83
- }), fn = (t) => t.quote !== void 0 && t.start !== void 0 && t.end !== void 0, gn = (t) => {
84
- const {
85
- id: e,
86
- creator: n,
87
- created: o,
88
- modified: r,
89
- target: i
90
- } = t, s = Array.isArray(i) ? i : [i], a = {
91
- creator: Ft(n),
92
- created: o ? new Date(o) : void 0,
93
- updated: r ? new Date(r) : void 0,
94
- annotation: e,
95
- selector: []
96
- };
97
- for (const u of s) {
98
- const g = (Array.isArray(u.selector) ? u.selector : [u.selector]).reduce((d, m) => {
99
- switch (m.type) {
100
- case "TextQuoteSelector":
101
- d.quote = m.exact;
102
- break;
103
- case "TextPositionSelector":
104
- d.start = m.start, d.end = m.end;
105
- break;
106
- }
107
- return d;
108
- }, {});
109
- if (fn(g))
110
- a.selector.push({ id: u.id, ...g });
111
- else {
112
- const d = [
113
- g.start ? void 0 : "TextPositionSelector",
114
- g.quote ? void 0 : "TextQuoteSelector"
115
- ].filter(Boolean);
116
- return { error: Error(`Missing selector types: ${d.join(" and ")} for annotation: ${t.id}`) };
117
- }
118
- }
119
- return { parsed: a };
120
- }, pn = (t) => {
121
- const e = t.id || Ht(), {
122
- creator: n,
123
- created: o,
124
- modified: r,
125
- body: i,
126
- ...s
127
- } = t, a = un(i, e), u = gn(t);
128
- return "error" in u ? { error: u.error } : {
129
- parsed: {
130
- ...s,
131
- id: e,
132
- bodies: a,
133
- target: u.parsed
134
- }
135
- };
136
- }, mn = (t, e, n) => {
137
- const { bodies: o, target: r, ...i } = t, {
138
- selector: s,
139
- creator: a,
140
- created: u,
141
- updated: f,
142
- ...g
143
- } = r, d = s.map((m) => {
144
- const { quote: h, start: w, end: y, range: p } = m, { prefix: l, suffix: c } = oe(p, n), b = [{
145
- type: "TextQuoteSelector",
146
- exact: h,
147
- prefix: l,
148
- suffix: c
149
- }, {
150
- type: "TextPositionSelector",
151
- start: w,
152
- end: y
153
- }];
154
- return {
155
- ...g,
156
- id: m.id,
157
- source: e,
158
- selector: b
159
- };
160
- });
161
- return {
162
- ...i,
163
- "@context": "http://www.w3.org/ns/anno.jsonld",
164
- id: t.id,
165
- type: "Annotation",
166
- body: hn(t.bodies),
167
- creator: a,
168
- created: u == null ? void 0 : u.toISOString(),
169
- modified: f == null ? void 0 : f.toISOString(),
170
- target: d
171
- };
1
+ import { j as jsxRuntimeExports } from "./react-text-annotator.es9.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 { annotatingEnabled, style, filter, userSelectAction, user } = opts;
10
+ const { anno, setAnno } = useContext(AnnotoriousContext);
11
+ useEffect(() => {
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.setUserSelectAction(userSelectAction), [anno, userSelectAction]);
21
+ useEffect(() => anno == null ? void 0 : anno.setUser(user), [anno, user]);
22
+ useEffect(() => anno == null ? void 0 : anno.setAnnotatingEnabled(annotatingEnabled), [anno, annotatingEnabled]);
23
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: el, className, children });
172
24
  };
173
25
  export {
174
- Yt as NOT_ANNOTATABLE_CLASS,
175
- D as NOT_ANNOTATABLE_SELECTOR,
176
- Vn as W3CTextFormat,
177
- oe as getQuoteContext,
178
- pt as getRangeAnnotatableContents,
179
- pn as parseW3CTextAnnotation,
180
- mn as serializeW3CTextAnnotation
26
+ TextAnnotator
181
27
  };
182
28
  //# sourceMappingURL=react-text-annotator.es6.js.map