@huridocs/react-text-selection-handler 0.3.0 → 0.3.2
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/HandleTextSelection.d.ts.map +1 -1
- package/dist/HandleTextSelection.js +24 -2
- package/dist/HandleTextSelection.js.map +1 -1
- package/dist/getSelectedText.d.ts +2 -0
- package/dist/getSelectedText.d.ts.map +1 -0
- package/dist/getSelectedText.js +46 -0
- package/dist/getSelectedText.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/HandleTextSelection.tsx +28 -3
- package/src/getSelectedText.ts +51 -0
- package/src/index.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleTextSelection.d.ts","sourceRoot":"","sources":["../src/HandleTextSelection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"HandleTextSelection.d.ts","sourceRoot":"","sources":["../src/HandleTextSelection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAqB,MAAM,OAAO,CAAC;AAGpE,OAAO,EAA+B,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG7E,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,GAAG,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAcD,QAAA,MAAM,mBAAmB,EAAE,iBAAiB,CAAC,qBAAqB,CAgFjE,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { useRef } from 'react';
|
|
1
|
+
import React, { useRef, useEffect } from 'react';
|
|
2
2
|
import { elementContainsDomRect } from './elementContainsDomRect';
|
|
3
3
|
import { rangeToTextRects } from './rangeToTextRects';
|
|
4
4
|
import { domRectToSelectionRectangle } from './TextSelection';
|
|
5
|
+
import { getSelectedText } from './getSelectedText';
|
|
5
6
|
const notNull = (value) => value !== null;
|
|
6
7
|
const normalizedFirefoxRange = (selection) => {
|
|
7
8
|
const finalRange = selection.getRangeAt(selection.rangeCount - 1);
|
|
@@ -33,8 +34,29 @@ const HandleTextSelection = ({ onSelect, onDeselect = () => { }, children, }) =>
|
|
|
33
34
|
return domRectToSelectionRectangle(rectangle, region);
|
|
34
35
|
})
|
|
35
36
|
.filter(notNull);
|
|
36
|
-
|
|
37
|
+
const text = getSelectedText();
|
|
38
|
+
onSelect({ text, selectionRectangles });
|
|
37
39
|
};
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const refElement = ref.current;
|
|
42
|
+
if (!refElement) {
|
|
43
|
+
return () => { };
|
|
44
|
+
}
|
|
45
|
+
const handleKeyDown = (event) => {
|
|
46
|
+
if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
const selection = window.getSelection();
|
|
49
|
+
if (selection && selection.toString().trim()) {
|
|
50
|
+
const text = getSelectedText();
|
|
51
|
+
navigator.clipboard.writeText(text);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
refElement.addEventListener('keydown', handleKeyDown);
|
|
56
|
+
return () => {
|
|
57
|
+
refElement.removeEventListener('keydown', handleKeyDown);
|
|
58
|
+
};
|
|
59
|
+
}, [ref]);
|
|
38
60
|
return (React.createElement("div", { role: "none", ref: ref, onMouseDown: e => {
|
|
39
61
|
var _a;
|
|
40
62
|
if (e.button !== 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleTextSelection.js","sourceRoot":"","sources":["../src/HandleTextSelection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAqB,MAAM,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"HandleTextSelection.js","sourceRoot":"","sources":["../src/HandleTextSelection.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSelectedText.d.ts","sourceRoot":"","sources":["../src/getSelectedText.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,eAAe,QAAO,MAiBlC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const isElementOnNextLine = (firstElement, secondElement) => {
|
|
2
|
+
var _a, _b;
|
|
3
|
+
if (!firstElement || !secondElement)
|
|
4
|
+
return false;
|
|
5
|
+
const left1 = (_a = firstElement === null || firstElement === void 0 ? void 0 : firstElement.style) === null || _a === void 0 ? void 0 : _a.left;
|
|
6
|
+
const left2 = (_b = secondElement === null || secondElement === void 0 ? void 0 : secondElement.style) === null || _b === void 0 ? void 0 : _b.left;
|
|
7
|
+
return parseFloat(left1) > parseFloat(left2);
|
|
8
|
+
};
|
|
9
|
+
const prepareSelectedElements = () => {
|
|
10
|
+
const selection = window.getSelection();
|
|
11
|
+
if (!selection || !selection.rangeCount)
|
|
12
|
+
return [];
|
|
13
|
+
const range = selection.getRangeAt(0);
|
|
14
|
+
const selectedContent = range.cloneContents();
|
|
15
|
+
const selectedElements = Array.from(selectedContent.querySelectorAll('*')).filter(element => !element.children.length);
|
|
16
|
+
const elements = [];
|
|
17
|
+
selectedElements.forEach((element, idx) => {
|
|
18
|
+
const previousElement = selectedElements[idx - 1];
|
|
19
|
+
if (previousElement) {
|
|
20
|
+
if (isElementOnNextLine(previousElement, element)) {
|
|
21
|
+
const spacer = document.createElement('span');
|
|
22
|
+
spacer.innerText = ' ';
|
|
23
|
+
elements.push(spacer);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
elements.push(element);
|
|
27
|
+
});
|
|
28
|
+
return elements;
|
|
29
|
+
};
|
|
30
|
+
export const getSelectedText = () => {
|
|
31
|
+
const elementsSelected = prepareSelectedElements();
|
|
32
|
+
if (elementsSelected.length <= 1) {
|
|
33
|
+
const selection = window.getSelection();
|
|
34
|
+
return (selection && selection.toString()) || '';
|
|
35
|
+
}
|
|
36
|
+
const selectedText = elementsSelected.reduce((acc, el) => {
|
|
37
|
+
let newText = acc;
|
|
38
|
+
newText += el.innerText;
|
|
39
|
+
if (el.tagName === 'BR') {
|
|
40
|
+
newText += '\n';
|
|
41
|
+
}
|
|
42
|
+
return newText;
|
|
43
|
+
}, '');
|
|
44
|
+
return selectedText;
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=getSelectedText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSelectedText.js","sourceRoot":"","sources":["../src/getSelectedText.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,CAAC,YAAyB,EAAE,aAA0B,EAAE,EAAE;;IACpF,IAAI,CAAC,YAAY,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,KAAK,GAAG,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,0CAAE,IAAI,CAAC;IACxC,MAAM,KAAK,GAAG,MAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,KAAK,0CAAE,IAAI,CAAC;IACzC,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,GAAkB,EAAE;IAClD,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAEnD,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;IAC9C,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAC/E,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CACd,CAAC;IACxB,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,gBAAgB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;QACxC,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAClD,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,mBAAmB,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE,CAAC;gBAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBAC9C,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE;IAC1C,MAAM,gBAAgB,GAAG,uBAAuB,EAAE,CAAC;IACnD,IAAI,gBAAgB,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QACxC,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE;QACvD,IAAI,OAAO,GAAG,GAAG,CAAC;QAClB,OAAO,IAAI,EAAE,CAAC,SAAS,CAAC;QACxB,IAAI,EAAE,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO,IAAI,IAAI,CAAC;QAClB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Highlight } from './Highlight';
|
|
2
2
|
export { HandleTextSelection } from './HandleTextSelection';
|
|
3
3
|
export { SelectionRegion } from './SelectionRegion';
|
|
4
|
+
export type { TextSelection, SelectionRectangle } from './TextSelection';
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huridocs/react-text-selection-handler",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"main": "./dist/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/index.js"
|
|
8
|
+
},
|
|
5
9
|
"description": "React pdf handler allows to render a PDF and handle text selection and highlights.",
|
|
6
10
|
"author": "HURIDOCS",
|
|
7
11
|
"license": "Apache-2.0",
|
|
@@ -20,7 +24,7 @@
|
|
|
20
24
|
"prepublish": "yarn build",
|
|
21
25
|
"before_publish": "yarn eslint && yarn check-types && yarn test",
|
|
22
26
|
"publish_to_npm": "np --access=public --testScript before_publish",
|
|
23
|
-
"build-test-app": "webpack --config ./e2e/webpack.config.
|
|
27
|
+
"build-test-app": "webpack --config ./e2e/webpack.config.cjs",
|
|
24
28
|
"test": "yarn build && yarn build-test-app && jest --projects e2e/jest.e2e.config.ts",
|
|
25
29
|
"build": "tsc --build tsconfig.build.json",
|
|
26
30
|
"eslint": "./node_modules/.bin/eslint e2e src --quiet --ext ts,tsx",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { FunctionComponent, useRef } from 'react';
|
|
1
|
+
import React, { FunctionComponent, useRef, useEffect } from 'react';
|
|
2
2
|
import { elementContainsDomRect } from './elementContainsDomRect';
|
|
3
3
|
import { rangeToTextRects } from './rangeToTextRects';
|
|
4
4
|
import { domRectToSelectionRectangle, TextSelection } from './TextSelection';
|
|
5
|
+
import { getSelectedText } from './getSelectedText';
|
|
5
6
|
|
|
6
7
|
interface SelectionHandlerProps {
|
|
7
8
|
onSelect: (textSelection: TextSelection) => any;
|
|
@@ -51,10 +52,34 @@ const HandleTextSelection: FunctionComponent<SelectionHandlerProps> = ({
|
|
|
51
52
|
return domRectToSelectionRectangle(rectangle, region);
|
|
52
53
|
})
|
|
53
54
|
.filter(notNull);
|
|
54
|
-
|
|
55
|
-
onSelect({ text
|
|
55
|
+
const text = getSelectedText();
|
|
56
|
+
onSelect({ text, selectionRectangles });
|
|
56
57
|
};
|
|
57
58
|
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
const refElement = ref.current;
|
|
61
|
+
|
|
62
|
+
if (!refElement) {
|
|
63
|
+
return () => {};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
67
|
+
if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
const selection = window.getSelection();
|
|
70
|
+
if (selection && selection.toString().trim()) {
|
|
71
|
+
const text = getSelectedText();
|
|
72
|
+
navigator.clipboard.writeText(text);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
refElement.addEventListener('keydown', handleKeyDown);
|
|
78
|
+
return () => {
|
|
79
|
+
refElement.removeEventListener('keydown', handleKeyDown);
|
|
80
|
+
};
|
|
81
|
+
}, [ref]);
|
|
82
|
+
|
|
58
83
|
return (
|
|
59
84
|
<div
|
|
60
85
|
role="none"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const isElementOnNextLine = (firstElement: HTMLElement, secondElement: HTMLElement) => {
|
|
2
|
+
if (!firstElement || !secondElement) return false;
|
|
3
|
+
const left1 = firstElement?.style?.left;
|
|
4
|
+
const left2 = secondElement?.style?.left;
|
|
5
|
+
return parseFloat(left1) > parseFloat(left2);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const prepareSelectedElements = (): HTMLElement[] => {
|
|
9
|
+
const selection = window.getSelection();
|
|
10
|
+
if (!selection || !selection.rangeCount) return [];
|
|
11
|
+
|
|
12
|
+
const range = selection.getRangeAt(0);
|
|
13
|
+
const selectedContent = range.cloneContents();
|
|
14
|
+
const selectedElements = Array.from(selectedContent.querySelectorAll('*')).filter(
|
|
15
|
+
element => !element.children.length
|
|
16
|
+
) as Array<HTMLElement>;
|
|
17
|
+
const elements: HTMLElement[] = [];
|
|
18
|
+
|
|
19
|
+
selectedElements.forEach((element, idx) => {
|
|
20
|
+
const previousElement = selectedElements[idx - 1];
|
|
21
|
+
if (previousElement) {
|
|
22
|
+
if (isElementOnNextLine(previousElement, element)) {
|
|
23
|
+
const spacer = document.createElement('span');
|
|
24
|
+
spacer.innerText = ' ';
|
|
25
|
+
elements.push(spacer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
elements.push(element);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return elements;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const getSelectedText = (): string => {
|
|
35
|
+
const elementsSelected = prepareSelectedElements();
|
|
36
|
+
if (elementsSelected.length <= 1) {
|
|
37
|
+
const selection = window.getSelection();
|
|
38
|
+
return (selection && selection.toString()) || '';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const selectedText = elementsSelected.reduce((acc, el) => {
|
|
42
|
+
let newText = acc;
|
|
43
|
+
newText += el.innerText;
|
|
44
|
+
if (el.tagName === 'BR') {
|
|
45
|
+
newText += '\n';
|
|
46
|
+
}
|
|
47
|
+
return newText;
|
|
48
|
+
}, '');
|
|
49
|
+
|
|
50
|
+
return selectedText;
|
|
51
|
+
};
|
package/src/index.ts
CHANGED