From a12404dc3efedfea25dd288631b66f8407ed2a3a Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Mon, 1 Jul 2024 19:52:38 +0300 Subject: [PATCH 01/38] Added height-based underline offset handling --- .../text-annotator/src/highlight/span/spansRenderer.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.ts b/packages/text-annotator/src/highlight/span/spansRenderer.ts index b6026726..705e06ee 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.ts +++ b/packages/text-annotator/src/highlight/span/spansRenderer.ts @@ -2,7 +2,7 @@ import type { ViewportState } from '@annotorious/core'; import { colord } from 'colord'; import { dequal } from 'dequal/lite'; import type { Rect, TextAnnotatorState } from '../../state'; -import { paint, type HighlightPainter } from '../HighlightPainter'; +import { type HighlightPainter, paint } from '../HighlightPainter'; import type { ViewportBounds } from '../viewport'; import { createBaseRenderer, type RendererImplementation } from '../baseRenderer'; import type { Highlight } from '../Highlight'; @@ -71,12 +71,10 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { span.style.width = `${rect.width}px`; span.style.height = `${rect.height}px`; - const backgroundColor = colord(style?.fill || DEFAULT_STYLE.fill) + span.style.backgroundColor = colord(style?.fill || DEFAULT_STYLE.fill) .alpha(style?.fillOpacity === undefined ? DEFAULT_STYLE.fillOpacity : style.fillOpacity) .toHex(); - span.style.backgroundColor = backgroundColor; - if (style.underlineStyle) span.style.borderStyle = style.underlineStyle; @@ -87,7 +85,7 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { span.style.borderBottomWidth = `${style.underlineThickness}px`; if (style.underlineOffset) - span.style.paddingBottom = `${style.underlineOffset}px`; + span.style.height = `${rect.height + style.underlineOffset}px` highlightLayer.appendChild(span); } From dfdaeb99b40b110956fa834386f7bff41673e2cb Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Mon, 1 Jul 2024 20:01:49 +0300 Subject: [PATCH 02/38] Added `box-sizing: border-box` definition to the examples --- packages/extension-tei/test/index.html | 134 ++-- packages/text-annotator-react/test/index.html | 80 +- packages/text-annotator/test/index.html | 751 +++++++++--------- 3 files changed, 489 insertions(+), 476 deletions(-) diff --git a/packages/extension-tei/test/index.html b/packages/extension-tei/test/index.html index 13624dfe..e0c2247b 100644 --- a/packages/extension-tei/test/index.html +++ b/packages/extension-tei/test/index.html @@ -6,83 +6,87 @@ -
-
+
+
+ + + anno.on('viewportIntersect', (annotations) => { + console.log('viewport', annotations); + }); + }); + }; + - \ No newline at end of file + diff --git a/packages/text-annotator-react/test/index.html b/packages/text-annotator-react/test/index.html index f0508218..f9076606 100644 --- a/packages/text-annotator-react/test/index.html +++ b/packages/text-annotator-react/test/index.html @@ -5,49 +5,53 @@ RecogitoJS React -
- - +
+ + - \ No newline at end of file + diff --git a/packages/text-annotator/test/index.html b/packages/text-annotator/test/index.html index 18db98c0..ad9055d3 100644 --- a/packages/text-annotator/test/index.html +++ b/packages/text-annotator/test/index.html @@ -5,395 +5,400 @@ RecogitoJS 3 - - - -
- - -
- -
-

Homer: The Odyssey

- -

- Tell me, O muse, of that ingenious hero who travelled far and wide after he had sacked the famous town of Troy. - Many cities did he visit, and many were the nations with whose manners and customs he was acquainted; moreover - he suffered much by sea while trying to save his own life and bring his men safely home; but do what he might he - could not save his men, for they perished through their own sheer folly in eating the cattle of the Sun-god - Hyperion; so the god prevented them from ever reaching home. Tell me, too, about all these things, O daughter of - Jove, from whatsoever source you may know them. -

- -
- Parent not annotabtale! - And its sub-element -
- -

- So now all who escaped death in battle or by shipwreck had got safely home except Ulysses, and he, though he was - longing to return to his wife and country, was detained by the goddess Calypso, who had got him into a large - cave and wanted to marry him. But as years went by, there came a time when the gods settled that he should go - back to Ithaca; even then, however, when he was among his own people, his troubles were not yet over; - nevertheless all the gods had now begun to pity him except Neptune, who still persecuted him without ceasing and - would not let him get home. -

- -
- Parent annotatable! - But its sub-element is not! -
- -

- Now Neptune had gone off to the Ethiopians, who are at the world's end, and lie in two halves, the one looking - West and the other East. He had gone there to accept a hecatomb of sheep and oxen, and was enjoying himself at - his festival; but the other gods met in the house of Olympian Jove, and the sire of gods and men spoke first. At - that moment he was thinking of Aegisthus, who had been killed by Agamemnon's son Orestes; so he said to the - other gods: -

- -
-

Not annotatable block!

-

- "See now, how men lay blame upon us gods for what is after all nothing but their own folly. Look at Aegisthus; - he must needs make love to Agamemnon's wife unrighteously and then kill Agamemnon, though he knew it would be - the death of him; for I sent Mercury to warn him not to do either of these things, inasmuch as Orestes would be - sure to take his revenge when he grew up and wanted to return home. Mercury told him this in all good will but - he would not listen, and now he has paid for everything in full." -

-
- -

- Then Minerva said, "Father, son of Saturn, King of kings, it served Aegisthus right, and so it would any one - else who does as he did; but Aegisthus is neither here nor there; it is for Ulysses that my heart bleeds, when I - think of his sufferings in that lonely sea-girt island, far away, poor man, from all his friends. It is an - island covered with forest, in the very middle of the sea, and a goddess lives there, daughter of the magician - Atlas, who looks after the bottom of the ocean, and carries the great columns that keep heaven and earth - asunder. This daughter of Atlas has got hold of poor unhappy Ulysses, and keeps trying by every kind of - blandishment to make him forget his home, so that he is tired of life, and thinks of nothing but how he may once - more see the smoke of his own chimneys. You, sir, take no heed of this, and yet when Ulysses was before Troy did - he not propitiate you with many a burnt sacrifice? Why then should you keep on being so angry with him?" -

- -

- And Jove said, "My child, what are you talking about? How can I forget Ulysses than whom there is no more - capable man on earth, nor more liberal in his offerings to the immortal gods that live in heaven? Bear in mind, - however, that Neptune is still furious with Ulysses for having blinded an eye of Polyphemus king of the - Cyclopes. Polyphemus is son to Neptune by the nymph Thoosa, daughter to the sea-king Phorcys; therefore though - he will not kill Ulysses outright, he torments him by preventing him from getting home. Still, let us lay our - heads together and see how we can help him to return; Neptune will then be pacified, for if we are all of a mind - he can hardly stand out against us." -

- -

- And Minerva said, "Father, son of Saturn, King of kings, if, then, the gods now mean that Ulysses should get - home, we should first send Mercury to the Ogygian island to tell Calypso that we have made up our minds and that - he is to return. In the meantime I will go to Ithaca, to put heart into Ulysses' son Telemachus; I will embolden - him to call the Achaeans in assembly, and speak out to the suitors of his mother Penelope, who persist in eating - up any number of his sheep and oxen; I will also conduct him to Sparta and to Pylos, to see if he can hear - anything about the return of his dear father- for this will make people speak well of him." -

- -

- Tell me, O muse, of that ingenious hero who travelled far and wide after he had sacked the famous town of Troy. - Many cities did he visit, and many were the nations with whose manners and customs he was acquainted; moreover - he suffered much by sea while trying to save his own life and bring his men safely home; but do what he might he - could not save his men, for they perished through their own sheer folly in eating the cattle of the Sun-god - Hyperion; so the god prevented them from ever reaching home. Tell me, too, about all these things, O daughter of - Jove, from whatsoever source you may know them. -

- -

- So now all who escaped death in battle or by shipwreck had got safely home except Ulysses, and he, though he was - longing to return to his wife and country, was detained by the goddess Calypso, who had got him into a large - cave and wanted to marry him. But as years went by, there came a time when the gods settled that he should go - back to Ithaca; even then, however, when he was among his own people, his troubles were not yet over; - nevertheless all the gods had now begun to pity him except Neptune, who still persecuted him without ceasing and - would not let him get home. -

+ *, *:before, *:after { + box-sizing: border-box; + } -

- Now Neptune had gone off to the Ethiopians, who are at the world's end, and lie in two halves, the one looking - West and the other East. He had gone there to accept a hecatomb of sheep and oxen, and was enjoying himself at - his festival; but the other gods met in the house of Olympian Jove, and the sire of gods and men spoke first. At - that moment he was thinking of Aegisthus, who had been killed by Agamemnon's son Orestes; so he said to the - other gods: -

+ html, body { + background: #e2e2e2; + padding: 0; + margin: 0; + display: flex; + flex-direction: row; + justify-content: center; + } -

- "See now, how men lay blame upon us gods for what is after all nothing but their own folly. Look at Aegisthus; - he must needs make love to Agamemnon's wife unrighteously and then kill Agamemnon, though he knew it would be - the death of him; for I sent Mercury to warn him not to do either of these things, inasmuch as Orestes would be - sure to take his revenge when he grew up and wanted to return home. Mercury told him this in all good will but - he would not listen, and now he has paid for everything in full." -

+ #content { + max-width: 800px; + background-color: #fff; + padding: 40px; + border-style: solid; + border-color: #cfcfcf; + border-width: 0 1px; + } -

- Then Minerva said, "Father, son of Saturn, King of kings, it served Aegisthus right, and so it would any one - else who does as he did; but Aegisthus is neither here nor there; it is for Ulysses that my heart bleeds, when I - think of his sufferings in that lonely sea-girt island, far away, poor man, from all his friends. It is an - island covered with forest, in the very middle of the sea, and a goddess lives there, daughter of the magician - Atlas, who looks after the bottom of the ocean, and carries the great columns that keep heaven and earth - asunder. This daughter of Atlas has got hold of poor unhappy Ulysses, and keeps trying by every kind of - blandishment to make him forget his home, so that he is tired of life, and thinks of nothing but how he may once - more see the smoke of his own chimneys. You, sir, take no heed of this, and yet when Ulysses was before Troy did - he not propitiate you with many a burnt sacrifice? Why then should you keep on being so angry with him?" -

+ #content .not-annotatable { + color: dimgray; + border: 3px solid wheat; + } -

- And Jove said, "My child, what are you talking about? How can I forget Ulysses than whom there is no more - capable man on earth, nor more liberal in his offerings to the immortal gods that live in heaven? Bear in mind, - however, that Neptune is still furious with Ulysses for having blinded an eye of Polyphemus king of the - Cyclopes. Polyphemus is son to Neptune by the nymph Thoosa, daughter to the sea-king Phorcys; therefore though - he will not kill Ulysses outright, he torments him by preventing him from getting home. Still, let us lay our - heads together and see how we can help him to return; Neptune will then be pacified, for if we are all of a mind - he can hardly stand out against us." -

+ h1 { + margin: 0; + padding: 0 0 20px 0; + } -

- And Minerva said, "Father, son of Saturn, King of kings, if, then, the gods now mean that Ulysses should get - home, we should first send Mercury to the Ogygian island to tell Calypso that we have made up our minds and that - he is to return. In the meantime I will go to Ithaca, to put heart into Ulysses' son Telemachus; I will embolden - him to call the Achaeans in assembly, and speak out to the suitors of his mother Penelope, who persist in eating - up any number of his sheep and oxen; I will also conduct him to Sparta and to Pylos, to see if he can hear - anything about the return of his dear father- for this will make people speak well of him." -

+ p { + font-size: 17px; + line-height: 160%; + } -

- Tell me, O muse, of that ingenious hero who travelled far and wide after he had sacked the famous town of Troy. - Many cities did he visit, and many were the nations with whose manners and customs he was acquainted; moreover - he suffered much by sea while trying to save his own life and bring his men safely home; but do what he might he - could not save his men, for they perished through their own sheer folly in eating the cattle of the Sun-god - Hyperion; so the god prevented them from ever reaching home. Tell me, too, about all these things, O daughter of - Jove, from whatsoever source you may know them. -

+ #buttons { + position: fixed; + top: 10px; + left: 10px; + z-index: 1; + } -

- So now all who escaped death in battle or by shipwreck had got safely home except Ulysses, and he, though he was - longing to return to his wife and country, was detained by the goddess Calypso, who had got him into a large - cave and wanted to marry him. But as years went by, there came a time when the gods settled that he should go - back to Ithaca; even then, however, when he was among his own people, his troubles were not yet over; - nevertheless all the gods had now begun to pity him except Neptune, who still persecuted him without ceasing and - would not let him get home. -

+ #debug { + position: fixed; + top: 0; + left: 0; + width: 100%; + text-align: right; + background-color: rgba(0, 0, 0, 0.75); + } -

- Now Neptune had gone off to the Ethiopians, who are at the world's end, and lie in two halves, the one looking - West and the other East. He had gone there to accept a hecatomb of sheep and oxen, and was enjoying himself at - his festival; but the other gods met in the house of Olympian Jove, and the sire of gods and men spoke first. At - that moment he was thinking of Aegisthus, who had been killed by Agamemnon's son Orestes; so he said to the - other gods: -

+ #debug p { + padding: 0; + margin: 0; + font-size: 0.8em; + color: #fff; + } + + + +
+ + +
+ +
+

Homer: The Odyssey

+ +

+ Tell me, O muse, of that ingenious hero who travelled far and wide after he had sacked the famous town of Troy. + Many cities did he visit, and many were the nations with whose manners and customs he was acquainted; moreover + he suffered much by sea while trying to save his own life and bring his men safely home; but do what he might he + could not save his men, for they perished through their own sheer folly in eating the cattle of the Sun-god + Hyperion; so the god prevented them from ever reaching home. Tell me, too, about all these things, O daughter of + Jove, from whatsoever source you may know them. +

+ +
+ Parent not annotabtale! + And its sub-element +
+ +

+ So now all who escaped death in battle or by shipwreck had got safely home except Ulysses, and he, though he was + longing to return to his wife and country, was detained by the goddess Calypso, who had got him into a large + cave and wanted to marry him. But as years went by, there came a time when the gods settled that he should go + back to Ithaca; even then, however, when he was among his own people, his troubles were not yet over; + nevertheless all the gods had now begun to pity him except Neptune, who still persecuted him without ceasing and + would not let him get home. +

+ +
+ Parent annotatable! + But its sub-element is not! +
+ +

+ Now Neptune had gone off to the Ethiopians, who are at the world's end, and lie in two halves, the one looking + West and the other East. He had gone there to accept a hecatomb of sheep and oxen, and was enjoying himself at + his festival; but the other gods met in the house of Olympian Jove, and the sire of gods and men spoke first. At + that moment he was thinking of Aegisthus, who had been killed by Agamemnon's son Orestes; so he said to the + other gods: +

+ +
+

Not annotatable block!

"See now, how men lay blame upon us gods for what is after all nothing but their own folly. Look at Aegisthus; he must needs make love to Agamemnon's wife unrighteously and then kill Agamemnon, though he knew it would be - the death of him; for I sent Mercury to warn him not to do either of these things, inasmuch as Orestes would be + the death of him; for I sent Mercury to warn him not to do either of these + things, inasmuch as Orestes would be sure to take his revenge when he grew up and wanted to return home. Mercury told him this in all good will but he would not listen, and now he has paid for everything in full."

- -

- Then Minerva said, "Father, son of Saturn, King of kings, it served Aegisthus right, and so it would any one - else who does as he did; but Aegisthus is neither here nor there; it is for Ulysses that my heart bleeds, when I - think of his sufferings in that lonely sea-girt island, far away, poor man, from all his friends. It is an - island covered with forest, in the very middle of the sea, and a goddess lives there, daughter of the magician - Atlas, who looks after the bottom of the ocean, and carries the great columns that keep heaven and earth - asunder. This daughter of Atlas has got hold of poor unhappy Ulysses, and keeps trying by every kind of - blandishment to make him forget his home, so that he is tired of life, and thinks of nothing but how he may once - more see the smoke of his own chimneys. You, sir, take no heed of this, and yet when Ulysses was before Troy did - he not propitiate you with many a burnt sacrifice? Why then should you keep on being so angry with him?" -

- -

- And Jove said, "My child, what are you talking about? How can I forget Ulysses than whom there is no more - capable man on earth, nor more liberal in his offerings to the immortal gods that live in heaven? Bear in mind, - however, that Neptune is still furious with Ulysses for having blinded an eye of Polyphemus king of the - Cyclopes. Polyphemus is son to Neptune by the nymph Thoosa, daughter to the sea-king Phorcys; therefore though - he will not kill Ulysses outright, he torments him by preventing him from getting home. Still, let us lay our - heads together and see how we can help him to return; Neptune will then be pacified, for if we are all of a mind - he can hardly stand out against us." -

- -

- And Minerva said, "Father, son of Saturn, King of kings, if, then, the gods now mean that Ulysses should get - home, we should first send Mercury to the Ogygian island to tell Calypso that we have made up our minds and that - he is to return. In the meantime I will go to Ithaca, to put heart into Ulysses' son Telemachus; I will embolden - him to call the Achaeans in assembly, and speak out to the suitors of his mother Penelope, who persist in eating - up any number of his sheep and oxen; I will also conduct him to Sparta and to Pylos, to see if he can hear - anything about the return of his dear father- for this will make people speak well of him." -

- +

+ Then Minerva said, "Father, son of Saturn, King of kings, it served Aegisthus right, and so it would any one + else who does as he did; but Aegisthus is neither here nor there; it is for Ulysses that my heart bleeds, when I + think of his sufferings in that lonely sea-girt island, far away, poor man, from all his friends. It is an + island covered with forest, in the very middle of the sea, and a goddess lives there, daughter of the magician + Atlas, who looks after the bottom of the ocean, and carries the great columns that keep heaven and earth + asunder. This daughter of Atlas has got hold of poor unhappy Ulysses, and keeps trying by every kind of + blandishment to make him forget his home, so that he is tired of life, and thinks of nothing but how he may once + more see the smoke of his own chimneys. You, sir, take no heed of this, and yet when Ulysses was before Troy did + he not propitiate you with many a burnt sacrifice? Why then should you keep on being so angry with him?" +

+ +

+ And Jove said, "My child, what are you talking about? How can I forget Ulysses than whom there is no more + capable man on earth, nor more liberal in his offerings to the immortal gods that live in heaven? Bear in mind, + however, that Neptune is still furious with Ulysses for having blinded an eye of Polyphemus king of the + Cyclopes. Polyphemus is son to Neptune by the nymph Thoosa, daughter to the sea-king Phorcys; therefore though + he will not kill Ulysses outright, he torments him by preventing him from getting home. Still, let us lay our + heads together and see how we can help him to return; Neptune will then be pacified, for if we are all of a mind + he can hardly stand out against us." +

+ +

+ And Minerva said, "Father, son of Saturn, King of kings, if, then, the gods now mean that Ulysses should get + home, we should first send Mercury to the Ogygian island to tell Calypso that we have made up our minds and that + he is to return. In the meantime I will go to Ithaca, to put heart into Ulysses' son Telemachus; I will embolden + him to call the Achaeans in assembly, and speak out to the suitors of his mother Penelope, who persist in eating + up any number of his sheep and oxen; I will also conduct him to Sparta and to Pylos, to see if he can hear + anything about the return of his dear father- for this will make people speak well of him." +

+ +

+ Tell me, O muse, of that ingenious hero who travelled far and wide after he had sacked the famous town of Troy. + Many cities did he visit, and many were the nations with whose manners and customs he was acquainted; moreover + he suffered much by sea while trying to save his own life and bring his men safely home; but do what he might he + could not save his men, for they perished through their own sheer folly in eating the cattle of the Sun-god + Hyperion; so the god prevented them from ever reaching home. Tell me, too, about all these things, O daughter of + Jove, from whatsoever source you may know them. +

+ +

+ So now all who escaped death in battle or by shipwreck had got safely home except Ulysses, and he, though he was + longing to return to his wife and country, was detained by the goddess Calypso, who had got him into a large + cave and wanted to marry him. But as years went by, there came a time when the gods settled that he should go + back to Ithaca; even then, however, when he was among his own people, his troubles were not yet over; + nevertheless all the gods had now begun to pity him except Neptune, who still persecuted him without ceasing and + would not let him get home. +

+ +

+ Now Neptune had gone off to the Ethiopians, who are at the world's end, and lie in two halves, the one looking + West and the other East. He had gone there to accept a hecatomb of sheep and oxen, and was enjoying himself at + his festival; but the other gods met in the house of Olympian Jove, and the sire of gods and men spoke first. At + that moment he was thinking of Aegisthus, who had been killed by Agamemnon's son Orestes; so he said to the + other gods: +

+ +

+ "See now, how men lay blame upon us gods for what is after all nothing but their own folly. Look at Aegisthus; + he must needs make love to Agamemnon's wife unrighteously and then kill Agamemnon, though he knew it would be + the death of him; for I sent Mercury to warn him not to do either of these things, inasmuch as Orestes would be + sure to take his revenge when he grew up and wanted to return home. Mercury told him this in all good will but + he would not listen, and now he has paid for everything in full." +

+ +

+ Then Minerva said, "Father, son of Saturn, King of kings, it served Aegisthus right, and so it would any one + else who does as he did; but Aegisthus is neither here nor there; it is for Ulysses that my heart bleeds, when I + think of his sufferings in that lonely sea-girt island, far away, poor man, from all his friends. It is an + island covered with forest, in the very middle of the sea, and a goddess lives there, daughter of the magician + Atlas, who looks after the bottom of the ocean, and carries the great columns that keep heaven and earth + asunder. This daughter of Atlas has got hold of poor unhappy Ulysses, and keeps trying by every kind of + blandishment to make him forget his home, so that he is tired of life, and thinks of nothing but how he may once + more see the smoke of his own chimneys. You, sir, take no heed of this, and yet when Ulysses was before Troy did + he not propitiate you with many a burnt sacrifice? Why then should you keep on being so angry with him?" +

+ +

+ And Jove said, "My child, what are you talking about? How can I forget Ulysses than whom there is no more + capable man on earth, nor more liberal in his offerings to the immortal gods that live in heaven? Bear in mind, + however, that Neptune is still furious with Ulysses for having blinded an eye of Polyphemus king of the + Cyclopes. Polyphemus is son to Neptune by the nymph Thoosa, daughter to the sea-king Phorcys; therefore though + he will not kill Ulysses outright, he torments him by preventing him from getting home. Still, let us lay our + heads together and see how we can help him to return; Neptune will then be pacified, for if we are all of a mind + he can hardly stand out against us." +

+ +

+ And Minerva said, "Father, son of Saturn, King of kings, if, then, the gods now mean that Ulysses should get + home, we should first send Mercury to the Ogygian island to tell Calypso that we have made up our minds and that + he is to return. In the meantime I will go to Ithaca, to put heart into Ulysses' son Telemachus; I will embolden + him to call the Achaeans in assembly, and speak out to the suitors of his mother Penelope, who persist in eating + up any number of his sheep and oxen; I will also conduct him to Sparta and to Pylos, to see if he can hear + anything about the return of his dear father- for this will make people speak well of him." +

+ +

+ Tell me, O muse, of that ingenious hero who travelled far and wide after he had sacked the famous town of Troy. + Many cities did he visit, and many were the nations with whose manners and customs he was acquainted; moreover + he suffered much by sea while trying to save his own life and bring his men safely home; but do what he might he + could not save his men, for they perished through their own sheer folly in eating the cattle of the Sun-god + Hyperion; so the god prevented them from ever reaching home. Tell me, too, about all these things, O daughter of + Jove, from whatsoever source you may know them. +

+ +

+ So now all who escaped death in battle or by shipwreck had got safely home except Ulysses, and he, though he was + longing to return to his wife and country, was detained by the goddess Calypso, who had got him into a large + cave and wanted to marry him. But as years went by, there came a time when the gods settled that he should go + back to Ithaca; even then, however, when he was among his own people, his troubles were not yet over; + nevertheless all the gods had now begun to pity him except Neptune, who still persecuted him without ceasing and + would not let him get home. +

+ +

+ Now Neptune had gone off to the Ethiopians, who are at the world's end, and lie in two halves, the one looking + West and the other East. He had gone there to accept a hecatomb of sheep and oxen, and was enjoying himself at + his festival; but the other gods met in the house of Olympian Jove, and the sire of gods and men spoke first. At + that moment he was thinking of Aegisthus, who had been killed by Agamemnon's son Orestes; so he said to the + other gods: +

+ +

+ "See now, how men lay blame upon us gods for what is after all nothing but their own folly. Look at Aegisthus; + he must needs make love to Agamemnon's wife unrighteously and then kill Agamemnon, though he knew it would be + the death of him; for I sent Mercury to warn him not to do either of these things, inasmuch as Orestes would be + sure to take his revenge when he grew up and wanted to return home. Mercury told him this in all good will but + he would not listen, and now he has paid for everything in full." +

+ +

+ Then Minerva said, "Father, son of Saturn, King of kings, it served Aegisthus right, and so it would any one + else who does as he did; but Aegisthus is neither here nor there; it is for Ulysses that my heart bleeds, when I + think of his sufferings in that lonely sea-girt island, far away, poor man, from all his friends. It is an + island covered with forest, in the very middle of the sea, and a goddess lives there, daughter of the magician + Atlas, who looks after the bottom of the ocean, and carries the great columns that keep heaven and earth + asunder. This daughter of Atlas has got hold of poor unhappy Ulysses, and keeps trying by every kind of + blandishment to make him forget his home, so that he is tired of life, and thinks of nothing but how he may once + more see the smoke of his own chimneys. You, sir, take no heed of this, and yet when Ulysses was before Troy did + he not propitiate you with many a burnt sacrifice? Why then should you keep on being so angry with him?" +

+ +

+ And Jove said, "My child, what are you talking about? How can I forget Ulysses than whom there is no more + capable man on earth, nor more liberal in his offerings to the immortal gods that live in heaven? Bear in mind, + however, that Neptune is still furious with Ulysses for having blinded an eye of Polyphemus king of the + Cyclopes. Polyphemus is son to Neptune by the nymph Thoosa, daughter to the sea-king Phorcys; therefore though + he will not kill Ulysses outright, he torments him by preventing him from getting home. Still, let us lay our + heads together and see how we can help him to return; Neptune will then be pacified, for if we are all of a mind + he can hardly stand out against us." +

+ +

+ And Minerva said, "Father, son of Saturn, King of kings, if, then, the gods now mean that Ulysses should get + home, we should first send Mercury to the Ogygian island to tell Calypso that we have made up our minds and that + he is to return. In the meantime I will go to Ithaca, to put heart into Ulysses' son Telemachus; I will embolden + him to call the Achaeans in assembly, and speak out to the suitors of his mother Penelope, who persist in eating + up any number of his sheep and oxen; I will also conduct him to Sparta and to Pylos, to see if he can hear + anything about the return of his dear father- for this will make people speak well of him." +

+
+ + From 8c3a481ee0d8c18e16cd037e73927af4d378f0b5 Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Mon, 8 Jul 2024 10:14:30 +0300 Subject: [PATCH 03/38] Added explicit `box-sizing: content-box` for the `span` annotations --- .../src/highlight/span/spansRenderer.css | 9 +++++++-- .../src/highlight/span/spansRenderer.ts | 20 +++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.css b/packages/text-annotator/src/highlight/span/spansRenderer.css index cd1b51c6..611a46ba 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.css +++ b/packages/text-annotator/src/highlight/span/spansRenderer.css @@ -12,8 +12,13 @@ } .r6o-annotatable .r6o-span-highlight-layer .r6o-annotation { - border-style: solid; - border-width: 0; position: absolute; display: block; + border-width: 0; + border-style: solid; +} + +.r6o-annotation { + /* `padding` should grow beyond the `height` and be used as the underline offset */ + box-sizing: content-box; } diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.ts b/packages/text-annotator/src/highlight/span/spansRenderer.ts index 705e06ee..19a04263 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.ts +++ b/packages/text-annotator/src/highlight/span/spansRenderer.ts @@ -21,7 +21,7 @@ const computeZIndex = (rect: Rect, all: Rect[]): number => { intersects(rect, other) && other.width > rect.width )).length; -} +}; const createRenderer = (container: HTMLElement): RendererImplementation => { @@ -36,12 +36,12 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { let currentRendered: Highlight[] = []; const redraw = ( - highlights: Highlight[], + highlights: Highlight[], viewportBounds: ViewportBounds, currentStyle?: HighlightStyleExpression, painter?: HighlightPainter, lazy?: boolean - ) => { + ) => { const noChanges = dequal(currentRendered, highlights); // If there are no changes and rendering is set to lazy @@ -85,7 +85,7 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { span.style.borderBottomWidth = `${style.underlineThickness}px`; if (style.underlineOffset) - span.style.height = `${rect.height + style.underlineOffset}px` + span.style.paddingBottom = `${style.underlineOffset}px`; highlightLayer.appendChild(span); } @@ -93,29 +93,29 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { }); currentRendered = highlights; - } + }; const setVisible = (visible: boolean) => { if (visible) highlightLayer.classList.remove('hidden'); else highlightLayer.classList.add('hidden'); - } + }; const destroy = () => { highlightLayer.remove(); - } + }; return { destroy, redraw, setVisible - } + }; -} +}; export const createSpansRenderer = ( - container: HTMLElement, + container: HTMLElement, state: TextAnnotatorState, viewport: ViewportState ) => createBaseRenderer(container, state, viewport, createRenderer(container)); From 617072b8df2f013da08f354d0d44cc6707321142 Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Mon, 8 Jul 2024 10:55:54 +0300 Subject: [PATCH 04/38] Removed extra `;` --- .../src/highlight/span/spansRenderer.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.ts b/packages/text-annotator/src/highlight/span/spansRenderer.ts index 19a04263..997acd10 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.ts +++ b/packages/text-annotator/src/highlight/span/spansRenderer.ts @@ -14,14 +14,14 @@ const computeZIndex = (rect: Rect, all: Rect[]): number => { const intersects = (a: Rect, b: Rect): boolean => ( a.x <= b.x + b.width && a.x + a.width >= b.x && a.y <= b.y + b.height && a.y + a.height >= b.y - ); + ) return all.filter(other => ( rect !== other && intersects(rect, other) && other.width > rect.width )).length; -}; +} const createRenderer = (container: HTMLElement): RendererImplementation => { @@ -93,18 +93,18 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { }); currentRendered = highlights; - }; + } const setVisible = (visible: boolean) => { if (visible) highlightLayer.classList.remove('hidden'); else highlightLayer.classList.add('hidden'); - }; + } const destroy = () => { highlightLayer.remove(); - }; + } return { destroy, @@ -112,10 +112,10 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { setVisible }; -}; +} export const createSpansRenderer = ( container: HTMLElement, state: TextAnnotatorState, viewport: ViewportState -) => createBaseRenderer(container, state, viewport, createRenderer(container)); +) => createBaseRenderer(container, state, viewport, createRenderer(container)) From e4b1a82edefa2674eaff6135818dd1106be5bab3 Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Thu, 25 Jul 2024 18:25:31 +0300 Subject: [PATCH 05/38] Formatting --- .../text-annotator/src/highlight/span/spansRenderer.css | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.css b/packages/text-annotator/src/highlight/span/spansRenderer.css index 11fb699c..1e4b7996 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.css +++ b/packages/text-annotator/src/highlight/span/spansRenderer.css @@ -13,14 +13,12 @@ } .r6o-annotatable .r6o-span-highlight-layer .r6o-annotation { + position: absolute; + display: block; border-style: solid; border-width: 0; - box-sizing: content-box; - display: block; - position: absolute; -} -.r6o-annotation { /* `padding` should grow beyond the `height` and be used as the underline offset */ box-sizing: content-box; } + From 709d9be7f38e9d07a2024165503765bcb8cc4061 Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Thu, 26 Sep 2024 16:22:24 +0300 Subject: [PATCH 06/38] Merged `main` into `#115-fix-spans-underlying-offset` --- packages/text-annotator-react/test/index.html | 74 ++++++----- packages/text-annotator/test/index.html | 118 +++++++++--------- 2 files changed, 94 insertions(+), 98 deletions(-) diff --git a/packages/text-annotator-react/test/index.html b/packages/text-annotator-react/test/index.html index 6e05d098..9bf3adec 100644 --- a/packages/text-annotator-react/test/index.html +++ b/packages/text-annotator-react/test/index.html @@ -5,53 +5,49 @@ RecogitoJS React diff --git a/packages/text-annotator/test/index.html b/packages/text-annotator/test/index.html index db4874c9..04aea80b 100644 --- a/packages/text-annotator/test/index.html +++ b/packages/text-annotator/test/index.html @@ -5,65 +5,65 @@ RecogitoJS 3 From 614f4c1b536812733ef61832229a5d9764529bec Mon Sep 17 00:00:00 2001 From: Oleksandr Danylchenko Date: Thu, 26 Sep 2024 16:23:06 +0300 Subject: [PATCH 07/38] Formatting --- packages/text-annotator-react/test/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/text-annotator-react/test/index.html b/packages/text-annotator-react/test/index.html index 9bf3adec..d9f53b5b 100644 --- a/packages/text-annotator-react/test/index.html +++ b/packages/text-annotator-react/test/index.html @@ -51,8 +51,8 @@ -
- - +
+ + From 47066df735617b950436b9c6ab34c21af2db563c Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 10:18:43 +0200 Subject: [PATCH 08/38] Selection behavior change: annotation gets created on pointer up, not immediately --- .../text-annotator/src/SelectionHandler.ts | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 164c4ed7..91b0ba49 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -95,10 +95,8 @@ export const SelectionHandler = ( } else if (sel.isCollapsed && timeDifference < CLICK_TIMEOUT) { - /* - Firefox doesn't fire the 'selectstart' when user clicks - over the text, which collapses the selection - */ + // Firefox doesn't fire the 'selectstart' when user clicks + // over the text, which collapses the selection onSelectStart(lastDownEvent || evt); } @@ -142,9 +140,11 @@ export const SelectionHandler = ( updated: new Date() }; + // On destkop, the annotation won't usually exist while the selection is + // being edited. But it will typcially be the case on mobile! if (store.getAnnotation(currentTarget.annotation)) { store.updateTarget(currentTarget, Origin.LOCAL); - } else { + } /* else { // Proper lifecycle management: clear selection first... selection.clear(); @@ -158,6 +158,7 @@ export const SelectionHandler = ( // ...then make the new annotation the current selection selection.userSelect(currentTarget.annotation, lastDownEvent); } + */ }); /** @@ -218,8 +219,19 @@ export const SelectionHandler = ( if (sel?.isCollapsed && timeDifference < CLICK_TIMEOUT) { currentTarget = undefined; clickSelect(); - } else if (currentTarget && store.getAnnotation(currentTarget.annotation)) { - selection.userSelect(currentTarget.annotation, evt); + } else if (currentTarget) { + // Proper lifecycle management: clear selection first... + selection.clear(); + + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + + // ...then make the new annotation the current selection + selection.userSelect(currentTarget.annotation, clonePointerEvent(evt)); } }); } From f786661f5ab7a1228f7281bd0effdfdb8973c167 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 10:45:56 +0200 Subject: [PATCH 09/38] Removed pointerup/keydown event requirement from popup --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index d001400e..237fb785 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -73,12 +73,13 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const { getFloatingProps } = useInteractions([dismiss, role]); const selectedKey = selected.map(a => a.annotation.id).join('-'); + useEffect(() => { // Ignore all selection changes except those accompanied by a user event. - if (selected.length > 0 && event) { - setOpen(event.type === 'pointerup' || event.type === 'keydown'); + if (selected.length > 0) { // && event) { + setOpen(true); // event.type === 'pointerup' || event.type === 'keydown'); } - }, [selectedKey, event]); + }, [selectedKey /*, event */]); useEffect(() => { // Close the popup if the selection is cleared From b96f04a192e3a68f1fc6e4c6c8e87a618027c9d5 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 10:48:18 +0200 Subject: [PATCH 10/38] Formatting --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 237fb785..b87443f1 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -1,4 +1,6 @@ -import React, { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react'; +import { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react'; +import { useAnnotator, useSelection } from '@annotorious/react'; +import type { TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; import { autoUpdate, flip, @@ -13,9 +15,6 @@ import { useRole } from '@floating-ui/react'; -import { useAnnotator, useSelection } from '@annotorious/react'; -import type { TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; - import './TextAnnotatorPopup.css'; interface TextAnnotationPopupProps { @@ -162,4 +161,4 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { ) : null; -}; +} From c14ed9909d09741d83a325c64d8bf705c5941bcf Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 11:06:59 +0200 Subject: [PATCH 11/38] Keyboard selection --- .../text-annotator/src/SelectionHandler.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 91b0ba49..b03caadb 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -236,6 +236,23 @@ export const SelectionHandler = ( }); } + const onKeyup = (evt: KeyboardEvent) => { + if (evt.key === 'Shift' && currentTarget) { + // Proper lifecycle management: clear selection first... + selection.clear(); + + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + + // ...then make the new annotation the current selection + selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); + } + } + hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, (evt) => { if (!evt.repeat) lastDownEvent = cloneKeyboardEvent(evt); @@ -267,6 +284,7 @@ export const SelectionHandler = ( document.addEventListener('pointerup', onPointerUp); if (annotatingEnabled) { + container.addEventListener('keyup', onKeyup); container.addEventListener('selectstart', onSelectStart); document.addEventListener('selectionchange', onSelectionChange); } @@ -275,6 +293,7 @@ export const SelectionHandler = ( container.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('pointerup', onPointerUp); + container.removeEventListener('keyup', onKeyup); container.removeEventListener('selectstart', onSelectStart); document.removeEventListener('selectionchange', onSelectionChange); From 9e3f045c81c0238775798b5aabf420ee8c5d8eb2 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 11:13:29 +0200 Subject: [PATCH 12/38] Addresses #139 in the revised selection model --- packages/text-annotator/src/SelectionHandler.ts | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index b03caadb..dbe05df8 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -117,6 +117,8 @@ export const SelectionHandler = ( store.deleteAnnotation(currentTarget.annotation); } + currentTarget = undefined; + return; } @@ -144,21 +146,7 @@ export const SelectionHandler = ( // being edited. But it will typcially be the case on mobile! if (store.getAnnotation(currentTarget.annotation)) { store.updateTarget(currentTarget, Origin.LOCAL); - } /* else { - // Proper lifecycle management: clear selection first... - selection.clear(); - - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); - - // ...then make the new annotation the current selection - selection.userSelect(currentTarget.annotation, lastDownEvent); } - */ }); /** From ead48404841271de4f3df97da8f2d368736956fb Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 11:25:08 +0200 Subject: [PATCH 13/38] Formatting --- packages/extension-tei/test/index.html | 139 +++++++++--------- .../src/highlight/span/spansRenderer.ts | 2 +- 2 files changed, 72 insertions(+), 69 deletions(-) diff --git a/packages/extension-tei/test/index.html b/packages/extension-tei/test/index.html index e0c2247b..b79bfdca 100644 --- a/packages/extension-tei/test/index.html +++ b/packages/extension-tei/test/index.html @@ -6,87 +6,90 @@ -
-
+
+
- + anno.on('viewportIntersect', (annotations) => { + console.log('viewport', annotations); + }); + }); + }; + - + \ No newline at end of file diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.ts b/packages/text-annotator/src/highlight/span/spansRenderer.ts index d9eb41e4..7932bbcc 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.ts +++ b/packages/text-annotator/src/highlight/span/spansRenderer.ts @@ -132,4 +132,4 @@ export const createSpansRenderer = ( container: HTMLElement, state: TextAnnotatorState, viewport: ViewportState -) => createBaseRenderer(container, state, viewport, createRenderer(container)) +) => createBaseRenderer(container, state, viewport, createRenderer(container)); From 9461812c76d82bb834ac9a751002b0cfc8df8a9c Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 11:54:44 +0200 Subject: [PATCH 14/38] Bugfix --- .../text-annotator/src/SelectionHandler.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index dbe05df8..ee67406d 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -117,8 +117,6 @@ export const SelectionHandler = ( store.deleteAnnotation(currentTarget.annotation); } - currentTarget = undefined; - return; } @@ -201,7 +199,7 @@ export const SelectionHandler = ( * @see https://github.com/recogito/text-annotator-js/issues/136 */ setTimeout(() => { - const sel = document.getSelection() + const sel = document.getSelection(); // Just a click, not a selection if (sel?.isCollapsed && timeDifference < CLICK_TIMEOUT) { @@ -226,18 +224,22 @@ export const SelectionHandler = ( const onKeyup = (evt: KeyboardEvent) => { if (evt.key === 'Shift' && currentTarget) { - // Proper lifecycle management: clear selection first... - selection.clear(); - - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); - - // ...then make the new annotation the current selection - selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); + const sel = document.getSelection(); + + if (!sel.isCollapsed) { + // Proper lifecycle management: clear selection first... + selection.clear(); + + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + + // ...then make the new annotation the current selection + selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); + } } } From e26b657fc115f8243c9bb75d1ca5cacf8550df0f Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 12:09:55 +0200 Subject: [PATCH 15/38] Upserting target instead of inserting on Shift up --- .../text-annotator/src/SelectionHandler.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index ee67406d..22b7bda6 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -230,12 +230,18 @@ export const SelectionHandler = ( // Proper lifecycle management: clear selection first... selection.clear(); - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); + const exists = store.getAnnotation(currentTarget.annotation); + if (exists) { + // ...then add annotation to store... + store.updateTarget(currentTarget); + } else { + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + } // ...then make the new annotation the current selection selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); From 08c8b71381a894c0140a8bf54000c63036432692 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 14:21:23 +0200 Subject: [PATCH 16/38] CTRL/CMD+A support --- .../text-annotator/src/SelectionHandler.ts | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 22b7bda6..b69f4591 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -19,10 +19,11 @@ const CLICK_TIMEOUT = 300; const ARROW_KEYS = ['up', 'down', 'left', 'right']; +const SELECT_ALL = ['ctrl+a', '⌘+a']; + const SELECTION_KEYS = [ ...ARROW_KEYS.map(key => `shift+${key}`), - 'ctrl+a', - '⌘+a' + ...SELECT_ALL ]; export const SelectionHandler = ( @@ -59,7 +60,6 @@ export const SelectionHandler = ( * Note that Chrome/iOS will sometimes return the root doc as target! */ const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); - currentTarget = annotatable ? { annotation: uuidv4(), selector: [], @@ -184,7 +184,7 @@ export const SelectionHandler = ( selection.userSelect(hovered.id, evt); } else if (!selection.isEmpty()) { selection.clear(); - } + } }; const timeDifference = evt.timeStamp - lastDownEvent.timeStamp; @@ -249,11 +249,30 @@ export const SelectionHandler = ( } } - hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, (evt) => { + const onSelectAll = (evt: KeyboardEvent) => { + onSelectStart(evt); + + // Proper lifecycle management: clear selection first... + selection.clear(); + + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + } + + hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, evt => { if (!evt.repeat) lastDownEvent = cloneKeyboardEvent(evt); }); + hotkeys(SELECT_ALL.join(','), { keydown: true, keyup: false}, evt => { + lastDownEvent = cloneKeyboardEvent(evt); + onSelectAll(evt); + }); + /** * Free caret movement through the text resets the annotation selection. * From 56c6670fa010aa10b358e9b56db95b4a438e88dc Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 14:27:03 +0200 Subject: [PATCH 17/38] Listening to event for mobile support --- packages/text-annotator/src/SelectionHandler.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index b69f4591..7781cefc 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -297,6 +297,7 @@ export const SelectionHandler = ( container.addEventListener('pointerdown', onPointerDown); document.addEventListener('pointerup', onPointerUp); + document.addEventListener('contextmenu', onPointerUp); if (annotatingEnabled) { container.addEventListener('keyup', onKeyup); @@ -307,6 +308,7 @@ export const SelectionHandler = ( const destroy = () => { container.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('pointerup', onPointerUp); + document.removeEventListener('contextmenu', onPointerUp); container.removeEventListener('keyup', onKeyup); container.removeEventListener('selectstart', onSelectStart); From 233254f1c5010252f66e25b9096d94665c527995 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 30 Sep 2024 15:38:45 +0200 Subject: [PATCH 18/38] Work in progress --- .../TextAnnotatorPopup/TextAnnotatorPopup.tsx | 126 ++++++------------ packages/text-annotator-react/test/App.tsx | 4 +- .../text-annotator/src/SelectionHandler.ts | 46 +++++-- 3 files changed, 81 insertions(+), 95 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index b87443f1..2ca3dcb4 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -1,13 +1,11 @@ -import { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react'; +import { ReactNode, useCallback, useEffect, useState, PointerEvent } from 'react'; import { useAnnotator, useSelection } from '@annotorious/react'; -import type { TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; +import { type TextAnnotation, type TextAnnotator } from '@recogito/text-annotator'; import { autoUpdate, - flip, - FloatingFocusManager, - FloatingPortal, inline, offset, + flip, shift, useDismiss, useFloating, @@ -15,18 +13,16 @@ import { useRole } from '@floating-ui/react'; -import './TextAnnotatorPopup.css'; - interface TextAnnotationPopupProps { popup(props: TextAnnotationPopupContentProps): ReactNode; } -export interface TextAnnotationPopupContentProps { +interface TextAnnotationPopupContentProps { annotation: TextAnnotation; - + editable?: boolean; event?: PointerEvent; @@ -37,27 +33,21 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const r = useAnnotator(); - const { selected, event } = useSelection(); + const { selected } = useSelection(); + const annotation = selected[0]?.annotation; const [isOpen, setOpen] = useState(selected?.length > 0); - const handleClose = () => { - r?.cancelSelected(); - }; - const { refs, floatingStyles, update, context } = useFloating({ placement: 'top', open: isOpen, - onOpenChange: (open, _event, reason) => { + /* onOpenChange: (open, _event, reason) => { setOpen(open); - - if (!open) { - if (reason === 'escape-key' || reason === 'focus-out') { - r?.cancelSelected(); - } + if (!open && reason === 'escape-key') { + r?.cancelSelected(); } - }, + }, */ middleware: [ offset(10), inline(), @@ -68,41 +58,33 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { }); const dismiss = useDismiss(context); - const role = useRole(context, { role: 'dialog' }); + + const role = useRole(context, { role: 'tooltip' }); + const { getFloatingProps } = useInteractions([dismiss, role]); const selectedKey = selected.map(a => a.annotation.id).join('-'); useEffect(() => { - // Ignore all selection changes except those accompanied by a user event. - if (selected.length > 0) { // && event) { - setOpen(true); // event.type === 'pointerup' || event.type === 'keydown'); - } - }, [selectedKey /*, event */]); + // Ignore all selection changes except those accompanied by a pointer event. + setOpen(selected.length > 0); + }, [selectedKey]); useEffect(() => { - // Close the popup if the selection is cleared - if (selected.length === 0 && isOpen) { - setOpen(false); - } - }, [isOpen, selectedKey]); + if (!isOpen || !annotation) return; - useEffect(() => { - if (isOpen && annotation) { - const { - target: { - selector: [{ range }] - } - } = annotation; - - refs.setPositionReference({ - getBoundingClientRect: range.getBoundingClientRect.bind(range), - getClientRects: range.getClientRects.bind(range) - }); - } else { - // Don't leave the reference depending on the previously selected annotation - refs.setPositionReference(null); - } + if (!annotation.target.selector || annotation.target.selector.length === 0) return; + + const { + target: { + selector: [{ range }] + } + } = annotation; + + refs.setPositionReference({ + getBoundingClientRect: () => range.getBoundingClientRect(), + getClientRects:() => range.getClientRects() + }); }, [isOpen, annotation, refs]); // Prevent text-annotator from handling the irrelevant events triggered from the popup @@ -122,43 +104,21 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { return () => { mutationObserver.disconnect(); window.document.removeEventListener('scroll', update, true); - }; + } }, [update]); return isOpen && selected.length > 0 ? ( - - -
- {props.popup({ - annotation: selected[0].annotation, - editable: selected[0].editable, - event - })} - - {/* It lets keyboard/sr users to know that the dialog closes when they focus out of it */} - -
-
-
+
+ {props.popup({ + annotation: selected[0].annotation, + editable: selected[0].editable + })} +
) : null; -} +} \ No newline at end of file diff --git a/packages/text-annotator-react/test/App.tsx b/packages/text-annotator-react/test/App.tsx index d638e588..a9064d57 100644 --- a/packages/text-annotator-react/test/App.tsx +++ b/packages/text-annotator-react/test/App.tsx @@ -1,9 +1,9 @@ import React, { FC, useCallback, useEffect } from 'react'; import { AnnotationBody, Annotorious, useAnnotationStore, useAnnotator, useSelection } from '@annotorious/react'; -import { TextAnnotator, TextAnnotatorPopup, type TextAnnotationPopupContentProps } from '../src'; +import { TextAnnotator, TextAnnotatorPopup } from '../src'; import { W3CTextFormat, type TextAnnotation, type TextAnnotator as RecogitoTextAnnotator } from '@recogito/text-annotator'; -const TestPopup: FC = (props) => { +const TestPopup = (props) => { const { annotation } = props; diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 7781cefc..d701fc4e 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -92,13 +92,11 @@ export const SelectionHandler = ( // Chrome/iOS does not reliably fire the 'selectstart' event! onSelectStart(lastDownEvent || evt); - } else if (sel.isCollapsed && timeDifference < CLICK_TIMEOUT) { // Firefox doesn't fire the 'selectstart' when user clicks // over the text, which collapses the selection onSelectStart(lastDownEvent || evt); - } } @@ -209,12 +207,18 @@ export const SelectionHandler = ( // Proper lifecycle management: clear selection first... selection.clear(); - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); + const exists = store.getAnnotation(currentTarget.annotation); + if (exists) { + // ...then add annotation to store... + store.updateTarget(currentTarget); + } else { + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + } // ...then make the new annotation the current selection selection.userSelect(currentTarget.annotation, clonePointerEvent(evt)); @@ -222,6 +226,28 @@ export const SelectionHandler = ( }); } + const onContextMenu = (evt: PointerEvent) => { + const sel = document.getSelection(); + if (sel?.isCollapsed) return; + + // selection.clear(); + + const exists = store.getAnnotation(currentTarget.annotation); + if (exists) { + // ...then add annotation to store... + store.updateTarget(currentTarget); + } else { + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + } + + selection.userSelect(currentTarget.annotation, clonePointerEvent(evt)); + } + const onKeyup = (evt: KeyboardEvent) => { if (evt.key === 'Shift' && currentTarget) { const sel = document.getSelection(); @@ -297,7 +323,7 @@ export const SelectionHandler = ( container.addEventListener('pointerdown', onPointerDown); document.addEventListener('pointerup', onPointerUp); - document.addEventListener('contextmenu', onPointerUp); + document.addEventListener('contextmenu', onContextMenu); if (annotatingEnabled) { container.addEventListener('keyup', onKeyup); @@ -308,7 +334,7 @@ export const SelectionHandler = ( const destroy = () => { container.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('pointerup', onPointerUp); - document.removeEventListener('contextmenu', onPointerUp); + document.removeEventListener('contextmenu', onContextMenu); container.removeEventListener('keyup', onKeyup); container.removeEventListener('selectstart', onSelectStart); From 4c5b09deaec28c4f917d19ea70942cce89852fd9 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Wed, 2 Oct 2024 14:19:37 +0200 Subject: [PATCH 19/38] Minor changes --- .../TextAnnotatorPopup/TextAnnotatorPopup.css | 6 +- .../TextAnnotatorPopup/TextAnnotatorPopup.tsx | 106 +++++++++++------- .../text-annotator/src/SelectionHandler.ts | 5 +- 3 files changed, 70 insertions(+), 47 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.css b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.css index 21ad1759..eec17ded 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.css +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.css @@ -3,7 +3,7 @@ * or the screen reader users as the popup behavior hint * Inspired by https://gist.github.com/ffoodd/000b59f431e3e64e4ce1a24d5bb36034 */ -.popup-close-message { +.r6o-popup-sr-only { border: 0 !important; clip: rect(1px, 1px, 1px, 1px); -webkit-clip-path: inset(50%); @@ -17,8 +17,8 @@ white-space: nowrap; } -.popup-close-message:focus, -.popup-close-message:active { +.r6o-popup-sr-only:focus, +.r6o-popup-sr-only:active { clip: auto; -webkit-clip-path: none; clip-path: none; diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 2ca3dcb4..a824c9df 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -1,11 +1,13 @@ -import { ReactNode, useCallback, useEffect, useState, PointerEvent } from 'react'; +import { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react'; import { useAnnotator, useSelection } from '@annotorious/react'; -import { type TextAnnotation, type TextAnnotator } from '@recogito/text-annotator'; +import type { TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; import { autoUpdate, + flip, + FloatingFocusManager, + FloatingPortal, inline, offset, - flip, shift, useDismiss, useFloating, @@ -13,16 +15,20 @@ import { useRole } from '@floating-ui/react'; +import './TextAnnotatorPopup.css'; + interface TextAnnotationPopupProps { + ariaCloseWarning?: string; + popup(props: TextAnnotationPopupContentProps): ReactNode; } -interface TextAnnotationPopupContentProps { +export interface TextAnnotationPopupContentProps { annotation: TextAnnotation; - + editable?: boolean; event?: PointerEvent; @@ -33,7 +39,7 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const r = useAnnotator(); - const { selected } = useSelection(); + const { selected, event } = useSelection(); const annotation = selected[0]?.annotation; @@ -42,12 +48,14 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const { refs, floatingStyles, update, context } = useFloating({ placement: 'top', open: isOpen, - /* onOpenChange: (open, _event, reason) => { + onOpenChange: (open, _event, reason) => { setOpen(open); - if (!open && reason === 'escape-key') { - r?.cancelSelected(); + + if (!open) { + if (reason === 'escape-key' || reason === 'focus-out') + r?.cancelSelected(); } - }, */ + }, middleware: [ offset(10), inline(), @@ -59,32 +67,29 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const dismiss = useDismiss(context); - const role = useRole(context, { role: 'tooltip' }); - - const { getFloatingProps } = useInteractions([dismiss, role]); + const role = useRole(context, { role: 'dialog' }); - const selectedKey = selected.map(a => a.annotation.id).join('-'); + const { getFloatingProps } = useInteractions([dismiss, role]); useEffect(() => { - // Ignore all selection changes except those accompanied by a pointer event. setOpen(selected.length > 0); - }, [selectedKey]); + }, [selected.map(a => a.annotation.id).join('-')]); useEffect(() => { - if (!isOpen || !annotation) return; - - if (!annotation.target.selector || annotation.target.selector.length === 0) return; - - const { - target: { - selector: [{ range }] - } - } = annotation; - - refs.setPositionReference({ - getBoundingClientRect: () => range.getBoundingClientRect(), - getClientRects:() => range.getClientRects() - }); + if (isOpen && annotation) { + const { + target: { + selector: [{ range }] + } + } = annotation; + + refs.setPositionReference({ + getBoundingClientRect: () => range.getBoundingClientRect(), + getClientRects: () => range.getClientRects() + }); + } else { + refs.setPositionReference(null); + } }, [isOpen, annotation, refs]); // Prevent text-annotator from handling the irrelevant events triggered from the popup @@ -104,21 +109,38 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { return () => { mutationObserver.disconnect(); window.document.removeEventListener('scroll', update, true); - } + }; }, [update]); return isOpen && selected.length > 0 ? ( -
- {props.popup({ - annotation: selected[0].annotation, - editable: selected[0].editable - })} -
+ + +
+ {props.popup({ + annotation: selected[0].annotation, + editable: selected[0].editable, + event + })} + + + {props.ariaCloseWarning || 'This dialog will close when you leave it.'} + +
+
+
) : null; } \ No newline at end of file diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index d701fc4e..8a89629b 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -228,15 +228,16 @@ export const SelectionHandler = ( const onContextMenu = (evt: PointerEvent) => { const sel = document.getSelection(); - if (sel?.isCollapsed) return; - // selection.clear(); + if (sel?.isCollapsed) return; const exists = store.getAnnotation(currentTarget.annotation); if (exists) { // ...then add annotation to store... store.updateTarget(currentTarget); } else { + selection.clear(); + // ...then add annotation to store... store.addAnnotation({ id: currentTarget.annotation, From 85e351a288417d523f60fc6d83f1f9d55bf63eae Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Wed, 2 Oct 2024 16:14:41 +0200 Subject: [PATCH 20/38] Mobile fixes (Android in particular) --- .../TextAnnotatorPopup/TextAnnotatorPopup.tsx | 19 +++--- .../src/TextAnnotatorPopup/isMobile.ts | 17 +++++ .../text-annotator/src/SelectionHandler.ts | 68 ++++++------------- 3 files changed, 50 insertions(+), 54 deletions(-) create mode 100644 packages/text-annotator-react/src/TextAnnotatorPopup/isMobile.ts diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index a824c9df..2c42fd65 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -1,6 +1,7 @@ import { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react'; import { useAnnotator, useSelection } from '@annotorious/react'; import type { TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; +import { isMobile } from './isMobile'; import { autoUpdate, flip, @@ -46,14 +47,12 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const [isOpen, setOpen] = useState(selected?.length > 0); const { refs, floatingStyles, update, context } = useFloating({ - placement: 'top', + placement: isMobile() ? 'bottom' : 'top', open: isOpen, onOpenChange: (open, _event, reason) => { - setOpen(open); - - if (!open) { - if (reason === 'escape-key' || reason === 'focus-out') - r?.cancelSelected(); + if (!open && (reason === 'escape-key' || reason === 'focus-out')) { + setOpen(open); + r?.cancelSelected(); } }, middleware: [ @@ -77,6 +76,9 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { useEffect(() => { if (isOpen && annotation) { + // Extra precaution - shouldn't normally happen + if (!annotation.target.selector || annotation.target.selector.length < 1) return; + const { target: { selector: [{ range }] @@ -120,8 +122,9 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { closeOnFocusOut={true} returnFocus={false} initialFocus={ - // Don't shift focus to the floating element when selected via keyboard - event?.type === 'keydown' ? -1 : 0 + // Don't shift focus to the floating element if selected via keyboard + // or on iPad/Android. + (event?.type === 'keydown' || isMobile()) ? -1 : 0 }>
{ + // @ts-ignore + var userAgent: string = navigator.userAgent || navigator.vendor || window.opera; + + if (/android/i.test(userAgent)) + return true; + + // @ts-ignore + // Note: as of recently, this NO LONGER DETECTS FIREFOX ON iOS! + // This means FF/iOS will behave like on the desktop, and loose + // selection handlebars after the popup opens. + if (/iPad|iPhone/.test(userAgent) && !window.MSStream) + return true; + + return false; +} \ No newline at end of file diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 8a89629b..76ac8270 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -162,6 +162,20 @@ export const SelectionHandler = ( isLeftClick = lastDownEvent.button === 0; }; + // Helper + const upsertCurrentTarget = () => { + const exists = store.getAnnotation(currentTarget.annotation); + if (exists) { + store.updateTarget(currentTarget); + } else { + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + } + } + const onPointerUp = (evt: PointerEvent) => { const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable || !isLeftClick) return; @@ -204,23 +218,8 @@ export const SelectionHandler = ( currentTarget = undefined; clickSelect(); } else if (currentTarget) { - // Proper lifecycle management: clear selection first... selection.clear(); - - const exists = store.getAnnotation(currentTarget.annotation); - if (exists) { - // ...then add annotation to store... - store.updateTarget(currentTarget); - } else { - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); - } - - // ...then make the new annotation the current selection + upsertCurrentTarget(); selection.userSelect(currentTarget.annotation, clonePointerEvent(evt)); } }); @@ -231,20 +230,12 @@ export const SelectionHandler = ( if (sel?.isCollapsed) return; - const exists = store.getAnnotation(currentTarget.annotation); - if (exists) { - // ...then add annotation to store... - store.updateTarget(currentTarget); - } else { - selection.clear(); - - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); - } + // When selecting the initial word, Chrome Android fires `contextmenu` + // before selectionChanged. + if (!currentTarget || currentTarget.selector.length === 0) + onSelectionChange(evt); + + upsertCurrentTarget(); selection.userSelect(currentTarget.annotation, clonePointerEvent(evt)); } @@ -254,23 +245,8 @@ export const SelectionHandler = ( const sel = document.getSelection(); if (!sel.isCollapsed) { - // Proper lifecycle management: clear selection first... selection.clear(); - - const exists = store.getAnnotation(currentTarget.annotation); - if (exists) { - // ...then add annotation to store... - store.updateTarget(currentTarget); - } else { - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); - } - - // ...then make the new annotation the current selection + upsertCurrentTarget(); selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); } } From c8000a115cded0393946b47fd87ca75d6860cd5d Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Wed, 2 Oct 2024 16:35:41 +0200 Subject: [PATCH 21/38] Device-specific 'select all' key --- packages/text-annotator/src/SelectionHandler.ts | 7 ++++--- packages/text-annotator/src/utils/device.ts | 2 ++ packages/text-annotator/src/utils/index.ts | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 packages/text-annotator/src/utils/device.ts diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 76ac8270..8c419c7a 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -10,6 +10,7 @@ import { debounce, splitAnnotatableRanges, rangeToSelector, + isMac, isWhitespaceOrEmpty, trimRangeToContainer, NOT_ANNOTATABLE_SELECTOR @@ -19,11 +20,11 @@ const CLICK_TIMEOUT = 300; const ARROW_KEYS = ['up', 'down', 'left', 'right']; -const SELECT_ALL = ['ctrl+a', '⌘+a']; +const SELECT_ALL = isMac ? '⌘+a' : 'ctrl+a'; const SELECTION_KEYS = [ ...ARROW_KEYS.map(key => `shift+${key}`), - ...SELECT_ALL + SELECT_ALL ]; export const SelectionHandler = ( @@ -271,7 +272,7 @@ export const SelectionHandler = ( lastDownEvent = cloneKeyboardEvent(evt); }); - hotkeys(SELECT_ALL.join(','), { keydown: true, keyup: false}, evt => { + hotkeys(SELECT_ALL, { keydown: true, keyup: false}, evt => { lastDownEvent = cloneKeyboardEvent(evt); onSelectAll(evt); }); diff --git a/packages/text-annotator/src/utils/device.ts b/packages/text-annotator/src/utils/device.ts new file mode 100644 index 00000000..a935d82a --- /dev/null +++ b/packages/text-annotator/src/utils/device.ts @@ -0,0 +1,2 @@ +// @ts-ignore +export const isMac = /mac/i.test(navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform); diff --git a/packages/text-annotator/src/utils/index.ts b/packages/text-annotator/src/utils/index.ts index f1284390..fe84a63b 100644 --- a/packages/text-annotator/src/utils/index.ts +++ b/packages/text-annotator/src/utils/index.ts @@ -1,4 +1,5 @@ export * from './cancelSingleClickEvents'; +export * from './device'; export * from './programmaticallyFocusable'; export * from './debounce'; export * from './getAnnotatableFragment'; From 4c7c67ef46f0e5141f98fef483cf49faa3aee683 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 07:43:23 +0200 Subject: [PATCH 22/38] Minor touch tweak --- packages/text-annotator/src/SelectionHandler.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 8c419c7a..579b6ac5 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -50,6 +50,8 @@ export const SelectionHandler = ( let lastDownEvent: Selection['event'] | undefined; + let isContextMenuOpen = false; + const onSelectStart = (evt: Event) => { if (isLeftClick === false) return; @@ -152,6 +154,8 @@ export const SelectionHandler = ( * to the initial pointerdown event and remember the button */ const onPointerDown = (evt: PointerEvent) => { + if (isContextMenuOpen) return; + const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable) return; @@ -178,6 +182,8 @@ export const SelectionHandler = ( } const onPointerUp = (evt: PointerEvent) => { + if (isContextMenuOpen) return; + const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable || !isLeftClick) return; @@ -227,6 +233,8 @@ export const SelectionHandler = ( } const onContextMenu = (evt: PointerEvent) => { + isContextMenuOpen = true; + const sel = document.getSelection(); if (sel?.isCollapsed) return; From 5d0af354faec05844ccb3729aed7340c4cbc9821 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 08:44:21 +0200 Subject: [PATCH 23/38] Bugfix/reverted broken change --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 5 ++--- packages/text-annotator/src/SelectionHandler.ts | 11 ++--------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 2c42fd65..1e941080 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -122,9 +122,8 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { closeOnFocusOut={true} returnFocus={false} initialFocus={ - // Don't shift focus to the floating element if selected via keyboard - // or on iPad/Android. - (event?.type === 'keydown' || isMobile()) ? -1 : 0 + // Don't shift focus to the floating element if selected via keyboard or on mobile. + (event?.type === 'keydown' || event?.type === 'contextmenu' || isMobile()) ? -1 : 0 }>
{ if (isLeftClick === false) return; @@ -154,8 +152,6 @@ export const SelectionHandler = ( * to the initial pointerdown event and remember the button */ const onPointerDown = (evt: PointerEvent) => { - if (isContextMenuOpen) return; - const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable) return; @@ -182,8 +178,6 @@ export const SelectionHandler = ( } const onPointerUp = (evt: PointerEvent) => { - if (isContextMenuOpen) return; - const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable || !isLeftClick) return; @@ -233,16 +227,15 @@ export const SelectionHandler = ( } const onContextMenu = (evt: PointerEvent) => { - isContextMenuOpen = true; - const sel = document.getSelection(); if (sel?.isCollapsed) return; // When selecting the initial word, Chrome Android fires `contextmenu` // before selectionChanged. - if (!currentTarget || currentTarget.selector.length === 0) + if (!currentTarget || currentTarget.selector.length === 0) { onSelectionChange(evt); + } upsertCurrentTarget(); From fb3d70bedba11660d64b479460094e951e530d38 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 09:17:09 +0200 Subject: [PATCH 24/38] Minor fix --- packages/text-annotator/src/SelectionHandler.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 948f9c61..440f2e34 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -50,7 +50,11 @@ export const SelectionHandler = ( let lastDownEvent: Selection['event'] | undefined; + let isContextMenuOpen = false; + const onSelectStart = (evt: Event) => { + isContextMenuOpen = false; + if (isLeftClick === false) return; @@ -152,6 +156,8 @@ export const SelectionHandler = ( * to the initial pointerdown event and remember the button */ const onPointerDown = (evt: PointerEvent) => { + if (isContextMenuOpen) return; + const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable) return; @@ -178,6 +184,8 @@ export const SelectionHandler = ( } const onPointerUp = (evt: PointerEvent) => { + if (isContextMenuOpen) return; + const annotatable = !(evt.target as Node).parentElement?.closest(NOT_ANNOTATABLE_SELECTOR); if (!annotatable || !isLeftClick) return; @@ -227,6 +235,8 @@ export const SelectionHandler = ( } const onContextMenu = (evt: PointerEvent) => { + isContextMenuOpen = true; + const sel = document.getSelection(); if (sel?.isCollapsed) return; From b2e62330d01cc0ccd4c91f905990d0579c33159c Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 09:39:34 +0200 Subject: [PATCH 25/38] Minor bugfix --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 12 +++++++----- packages/text-annotator/src/SelectionHandler.ts | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 1e941080..c5a476b1 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -1,4 +1,4 @@ -import { PointerEvent, ReactNode, useCallback, useEffect, useState } from 'react'; +import { PointerEvent, ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { useAnnotator, useSelection } from '@annotorious/react'; import type { TextAnnotation, TextAnnotator } from '@recogito/text-annotator'; import { isMobile } from './isMobile'; @@ -114,6 +114,11 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { }; }, [update]); + // Don't shift focus to the floating element if selected via keyboard or on mobile. + const initialFocus = useMemo(() => { + return (event?.type === 'keyup' || event?.type === 'contextmenu' || isMobile()) ? -1 : 0; + }, [event]); + return isOpen && selected.length > 0 ? ( { modal={false} closeOnFocusOut={true} returnFocus={false} - initialFocus={ - // Don't shift focus to the floating element if selected via keyboard or on mobile. - (event?.type === 'keydown' || event?.type === 'contextmenu' || isMobile()) ? -1 : 0 - }> + initialFocus={initialFocus}>
0) { selection.clear(); upsertCurrentTarget(); selection.userSelect(currentTarget.annotation, clonePointerEvent(evt)); From eb942a3de943da501cd89c59bc1fe5d355a7f286 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 10:00:11 +0200 Subject: [PATCH 26/38] 'Select All' workaround --- .../text-annotator/src/SelectionHandler.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index 0a5b15d6..da663440 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -271,12 +271,19 @@ export const SelectionHandler = ( // Proper lifecycle management: clear selection first... selection.clear(); - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); + setTimeout(() => { + // ...then add annotation to store... + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); + + selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); + + // Sigh.. not sure there's a reliable timeout. Alternative would be + // to listen to the selectionchange event once? + }, 250); } hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, evt => { From 9cf64f85160f13634a448273d68480b3d79d4ae7 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 10:13:42 +0200 Subject: [PATCH 27/38] Select-all fix --- .../text-annotator/src/SelectionHandler.ts | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index da663440..b2a98309 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -266,24 +266,30 @@ export const SelectionHandler = ( } const onSelectAll = (evt: KeyboardEvent) => { - onSelectStart(evt); - // Proper lifecycle management: clear selection first... - selection.clear(); + const onSelected = () => setTimeout(() => { + if (currentTarget?.selector.length > 0) { + selection.clear(); - setTimeout(() => { - // ...then add annotation to store... - store.addAnnotation({ - id: currentTarget.annotation, - bodies: [], - target: currentTarget - }); + store.addAnnotation({ + id: currentTarget.annotation, + bodies: [], + target: currentTarget + }); - selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); + selection.userSelect(currentTarget.annotation, cloneKeyboardEvent(evt)); + } + + document.removeEventListener('selectionchange', onSelected); - // Sigh.. not sure there's a reliable timeout. Alternative would be - // to listen to the selectionchange event once? - }, 250); + // Sigh... this needs a delay to work. But doesn't seem reliable. + }, 100); + + // Listen to the change event that follows + document.addEventListener('selectionchange', onSelected); + + // Start selection! + onSelectStart(evt); } hotkeys(SELECTION_KEYS.join(','), { element: container, keydown: true, keyup: false }, evt => { From 5adbeebbbd497f617b1355e9b76cc1d025bbcab7 Mon Sep 17 00:00:00 2001 From: Rainer Simon <470971+rsimon@users.noreply.github.com> Date: Thu, 3 Oct 2024 13:14:14 +0200 Subject: [PATCH 28/38] Update packages/text-annotator/src/SelectionHandler.ts Co-authored-by: Oleksandr Danylchenko <68850090+oleksandr-danylchenko@users.noreply.github.com> --- packages/text-annotator/src/SelectionHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index b2a98309..fd585270 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -206,7 +206,7 @@ export const SelectionHandler = ( } } else if (!selection.isEmpty()) { selection.clear(); - } + } }; const timeDifference = evt.timeStamp - lastDownEvent.timeStamp; From 28908cf0bca3f354ee8f344a918bf975b2a2e7ea Mon Sep 17 00:00:00 2001 From: Rainer Simon <470971+rsimon@users.noreply.github.com> Date: Thu, 3 Oct 2024 13:14:41 +0200 Subject: [PATCH 29/38] Update packages/text-annotator/src/SelectionHandler.ts Co-authored-by: Oleksandr Danylchenko <68850090+oleksandr-danylchenko@users.noreply.github.com> --- packages/text-annotator/src/SelectionHandler.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/text-annotator/src/SelectionHandler.ts b/packages/text-annotator/src/SelectionHandler.ts index fd585270..801e0f1c 100644 --- a/packages/text-annotator/src/SelectionHandler.ts +++ b/packages/text-annotator/src/SelectionHandler.ts @@ -143,8 +143,10 @@ export const SelectionHandler = ( updated: new Date() }; - // On destkop, the annotation won't usually exist while the selection is - // being edited. But it will typcially be the case on mobile! + /** + * During mouse selection on the desktop, annotation won't usually exist while the selection is being edited. + * But it will be typical during keyboard or mobile handlebars selection! + */ if (store.getAnnotation(currentTarget.annotation)) { store.updateTarget(currentTarget, Origin.LOCAL); } From 8d113dc93167df8d48521f331649202bf6cf32a1 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 13:20:38 +0200 Subject: [PATCH 30/38] Minor fix --- packages/text-annotator-react/test/App.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/text-annotator-react/test/App.tsx b/packages/text-annotator-react/test/App.tsx index a9064d57..74849e2c 100644 --- a/packages/text-annotator-react/test/App.tsx +++ b/packages/text-annotator-react/test/App.tsx @@ -1,9 +1,9 @@ import React, { FC, useCallback, useEffect } from 'react'; -import { AnnotationBody, Annotorious, useAnnotationStore, useAnnotator, useSelection } from '@annotorious/react'; -import { TextAnnotator, TextAnnotatorPopup } from '../src'; +import { AnnotationBody, Annotorious, useAnnotationStore, useAnnotator } from '@annotorious/react'; +import { TextAnnotationPopupContentProps, TextAnnotator, TextAnnotatorPopup } from '../src'; import { W3CTextFormat, type TextAnnotation, type TextAnnotator as RecogitoTextAnnotator } from '@recogito/text-annotator'; -const TestPopup = (props) => { +const TestPopup: FC = (props) => { const { annotation } = props; From 6758d7d3187edc374e37a8639a7ff20df1c9f421 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 14:54:24 +0200 Subject: [PATCH 31/38] Reverted to button for screenreader close hint --- .../TextAnnotatorPopup/TextAnnotatorPopup.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index c5a476b1..59170bc4 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -94,12 +94,6 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { } }, [isOpen, annotation, refs]); - // Prevent text-annotator from handling the irrelevant events triggered from the popup - const getStopEventsPropagationProps = useCallback( - () => ({ onPointerUp: (event: PointerEvent) => event.stopPropagation() }), - [] - ); - useEffect(() => { const config: MutationObserverInit = { attributes: true, childList: true, subtree: true }; @@ -114,11 +108,19 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { }; }, [update]); + // Prevent text-annotator from handling the irrelevant events triggered from the popup + const getStopEventsPropagationProps = useCallback( + () => ({ onPointerUp: (event: PointerEvent) => event.stopPropagation() }), + [] + ); + // Don't shift focus to the floating element if selected via keyboard or on mobile. const initialFocus = useMemo(() => { return (event?.type === 'keyup' || event?.type === 'contextmenu' || isMobile()) ? -1 : 0; }, [event]); + const onClose = () => r?.cancelSelected(); + return isOpen && selected.length > 0 ? ( { event })} - - {props.ariaCloseWarning || 'This dialog will close when you leave it.'} - +
From 95f7ff0093711cfc2d34df36672668a0da7feba5 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 3 Oct 2024 16:09:52 +0200 Subject: [PATCH 32/38] v3.0.0-rc.47 --- package-lock.json | 476 ++++++++++----------- package.json | 2 +- packages/extension-tei/package.json | 4 +- packages/text-annotator-react/package.json | 8 +- packages/text-annotator/package.json | 6 +- 5 files changed, 248 insertions(+), 248 deletions(-) diff --git a/package-lock.json b/package-lock.json index 91955eb6..8c05e545 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "license": "BSD-3-Clause", "workspaces": [ "./packages/text-annotator", @@ -101,13 +101,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -115,9 +115,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "dev": true, "license": "MIT", "engines": { @@ -125,22 +125,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -156,31 +156,31 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -189,30 +189,30 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -222,9 +222,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "dev": true, "license": "MIT", "engines": { @@ -232,23 +232,23 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, "license": "MIT", "engines": { @@ -256,9 +256,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, "license": "MIT", "engines": { @@ -266,9 +266,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "dev": true, "license": "MIT", "engines": { @@ -276,27 +276,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -306,13 +306,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.25.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -322,13 +322,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz", + "integrity": "sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -338,13 +338,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz", + "integrity": "sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -354,32 +354,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -388,14 +388,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1430,9 +1430,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz", - "integrity": "sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], @@ -1444,9 +1444,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.5.tgz", - "integrity": "sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], @@ -1458,9 +1458,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.5.tgz", - "integrity": "sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], @@ -1472,9 +1472,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.5.tgz", - "integrity": "sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], @@ -1486,9 +1486,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.5.tgz", - "integrity": "sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], @@ -1500,9 +1500,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.5.tgz", - "integrity": "sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], @@ -1514,9 +1514,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.5.tgz", - "integrity": "sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], @@ -1528,9 +1528,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.5.tgz", - "integrity": "sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], @@ -1542,9 +1542,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.5.tgz", - "integrity": "sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], @@ -1556,9 +1556,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.5.tgz", - "integrity": "sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], @@ -1570,9 +1570,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.5.tgz", - "integrity": "sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], @@ -1584,9 +1584,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.5.tgz", - "integrity": "sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], @@ -1598,9 +1598,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.5.tgz", - "integrity": "sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], @@ -1612,9 +1612,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.5.tgz", - "integrity": "sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], @@ -1626,9 +1626,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.5.tgz", - "integrity": "sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], @@ -1640,9 +1640,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.5.tgz", - "integrity": "sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], @@ -1908,9 +1908,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.10", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.10.tgz", - "integrity": "sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==", + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1963,14 +1963,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz", + "integrity": "sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/spy": "2.1.2", + "@vitest/utils": "2.1.2", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -1979,9 +1979,9 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.2.tgz", + "integrity": "sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==", "dev": true, "license": "MIT", "dependencies": { @@ -1993,7 +1993,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.1", + "@vitest/spy": "2.1.2", "msw": "^2.3.5", "vite": "^5.0.0" }, @@ -2007,9 +2007,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.2.tgz", + "integrity": "sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==", "dev": true, "license": "MIT", "dependencies": { @@ -2020,13 +2020,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.2.tgz", + "integrity": "sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.1", + "@vitest/utils": "2.1.2", "pathe": "^1.1.2" }, "funding": { @@ -2034,13 +2034,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.2.tgz", + "integrity": "sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.1", + "@vitest/pretty-format": "2.1.2", "magic-string": "^0.30.11", "pathe": "^1.1.2" }, @@ -2049,9 +2049,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.2.tgz", + "integrity": "sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==", "dev": true, "license": "MIT", "dependencies": { @@ -2062,13 +2062,13 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.2.tgz", + "integrity": "sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.1", + "@vitest/pretty-format": "2.1.2", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -2423,9 +2423,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001666", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz", + "integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==", "dev": true, "funding": [ { @@ -2709,9 +2709,9 @@ "license": "ISC" }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "version": "1.5.31", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.31.tgz", + "integrity": "sha512-QcDoBbQeYt0+3CWcK/rEbuHvwpbT/8SV9T3OSgs6cX1FlcUAkgrkqbg9zLnDrMM/rLamzQwal4LYFCiWk861Tg==", "dev": true, "license": "ISC" }, @@ -3195,16 +3195,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-schema-traverse": { @@ -3728,9 +3728,9 @@ } }, "node_modules/rollup": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", - "integrity": "sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "dev": true, "license": "MIT", "dependencies": { @@ -3744,22 +3744,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.5", - "@rollup/rollup-android-arm64": "4.22.5", - "@rollup/rollup-darwin-arm64": "4.22.5", - "@rollup/rollup-darwin-x64": "4.22.5", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.5", - "@rollup/rollup-linux-arm-musleabihf": "4.22.5", - "@rollup/rollup-linux-arm64-gnu": "4.22.5", - "@rollup/rollup-linux-arm64-musl": "4.22.5", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.5", - "@rollup/rollup-linux-riscv64-gnu": "4.22.5", - "@rollup/rollup-linux-s390x-gnu": "4.22.5", - "@rollup/rollup-linux-x64-gnu": "4.22.5", - "@rollup/rollup-linux-x64-musl": "4.22.5", - "@rollup/rollup-win32-arm64-msvc": "4.22.5", - "@rollup/rollup-win32-ia32-msvc": "4.22.5", - "@rollup/rollup-win32-x64-msvc": "4.22.5", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -4025,22 +4025,22 @@ } }, "node_modules/tldts": { - "version": "6.1.48", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", - "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==", + "version": "6.1.49", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.49.tgz", + "integrity": "sha512-E5se9HuCyfwWvmc0JiXiocOw+Cm4tlJCKewdB5RKMH8MmtiTsQCc+yu5BBYB5ZN4lNbz8Xg65bqJ1odS9+RhIA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.48" + "tldts-core": "^6.1.49" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.48", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz", - "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==", + "version": "6.1.49", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.49.tgz", + "integrity": "sha512-ctRO/wzBasOCxAStJG/60Qe8/QpGmaVPsE8djdk0vioxN4uCOgKoveH71Qc2EOmVMIjVf0BjigI5p9ZDuLOygg==", "dev": true, "license": "MIT" }, @@ -4287,9 +4287,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.2.tgz", + "integrity": "sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4359,19 +4359,19 @@ } }, "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.2.tgz", + "integrity": "sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/expect": "2.1.2", + "@vitest/mocker": "2.1.2", + "@vitest/pretty-format": "^2.1.2", + "@vitest/runner": "2.1.2", + "@vitest/snapshot": "2.1.2", + "@vitest/spy": "2.1.2", + "@vitest/utils": "2.1.2", "chai": "^5.1.1", "debug": "^4.3.6", "magic-string": "^0.30.11", @@ -4382,7 +4382,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.1", + "vite-node": "2.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -4397,8 +4397,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", + "@vitest/browser": "2.1.2", + "@vitest/ui": "2.1.2", "happy-dom": "*", "jsdom": "*" }, @@ -4555,7 +4555,7 @@ }, "packages/extension-tei": { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "license": "BSD-3-Clause", "devDependencies": { "CETEIcean": "^1.9.3", @@ -4565,12 +4565,12 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.9", - "@recogito/text-annotator": "3.0.0-rc.46" + "@recogito/text-annotator": "3.0.0-rc.47" } }, "packages/text-annotator": { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.9", @@ -4589,19 +4589,19 @@ "typescript": "5.6.2", "vite": "^5.4.8", "vite-plugin-dts": "^4.2.3", - "vitest": "^2.1.1" + "vitest": "^2.1.2" } }, "packages/text-annotator-react": { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.9", "@annotorious/react": "^3.0.9", "@floating-ui/react": "^0.26.24", - "@recogito/text-annotator": "3.0.0-rc.46", - "@recogito/text-annotator-tei": "3.0.0-rc.46", + "@recogito/text-annotator": "3.0.0-rc.47", + "@recogito/text-annotator-tei": "3.0.0-rc.47", "CETEIcean": "^1.9.3" }, "devDependencies": { diff --git a/package.json b/package.json index 9c749f96..011e1c76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "description": "Recogito Text Annotator monorepo", "author": "Rainer Simon", "repository": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index 36112eff..4c4afd6c 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "description": "Recogito Text Annotator TEI extension", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -33,6 +33,6 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.9", - "@recogito/text-annotator": "3.0.0-rc.46" + "@recogito/text-annotator": "3.0.0-rc.47" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index 30f10ddf..6715aea9 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "description": "Recogito Text Annotator React bindings", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -47,8 +47,8 @@ "@annotorious/core": "^3.0.9", "@annotorious/react": "^3.0.9", "@floating-ui/react": "^0.26.24", - "@recogito/text-annotator": "3.0.0-rc.46", - "@recogito/text-annotator-tei": "3.0.0-rc.46", + "@recogito/text-annotator": "3.0.0-rc.47", + "@recogito/text-annotator-tei": "3.0.0-rc.47", "CETEIcean": "^1.9.3" } -} +} \ No newline at end of file diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 5415aa5e..c96af286 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.46", + "version": "3.0.0-rc.47", "description": "A JavaScript text annotation library", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -34,7 +34,7 @@ "typescript": "5.6.2", "vite": "^5.4.8", "vite-plugin-dts": "^4.2.3", - "vitest": "^2.1.1" + "vitest": "^2.1.2" }, "dependencies": { "@annotorious/core": "^3.0.9", @@ -44,4 +44,4 @@ "rbush": "^4.0.1", "uuid": "^10.0.0" } -} +} \ No newline at end of file From a457f5960db15f60c6f3d6ce914f068fa8d82b79 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 4 Oct 2024 09:24:44 +0200 Subject: [PATCH 33/38] Minor fix --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 59170bc4..13bcdafd 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -71,14 +71,17 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const { getFloatingProps } = useInteractions([dismiss, role]); useEffect(() => { - setOpen(selected.length > 0); - }, [selected.map(a => a.annotation.id).join('-')]); + setOpen( + // Selected annotation exists and has a selector + annotation?.target.selector && + // The selector is not empty - use case: e.g. lazy loading PDF annotations, + // annotations created through plugins etc. + annotation.target.selector.length > 0 + ); + }, [annotation]); useEffect(() => { if (isOpen && annotation) { - // Extra precaution - shouldn't normally happen - if (!annotation.target.selector || annotation.target.selector.length < 1) return; - const { target: { selector: [{ range }] From 58f0a5f68c0099ae3e75e1a444d9e951af54f551 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 4 Oct 2024 09:26:12 +0200 Subject: [PATCH 34/38] package-lock.json --- package-lock.json | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8c05e545..c0c720c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2106,14 +2106,14 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.10.tgz", - "integrity": "sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.11.tgz", + "integrity": "sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.10", + "@vue/shared": "3.5.11", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" @@ -2127,14 +2127,14 @@ "license": "MIT" }, "node_modules/@vue/compiler-dom": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.10.tgz", - "integrity": "sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.11.tgz", + "integrity": "sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.10", - "@vue/shared": "3.5.10" + "@vue/compiler-core": "3.5.11", + "@vue/shared": "3.5.11" } }, "node_modules/@vue/compiler-vue2": { @@ -2200,9 +2200,9 @@ } }, "node_modules/@vue/shared": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.10.tgz", - "integrity": "sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.11.tgz", + "integrity": "sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==", "dev": true, "license": "MIT" }, @@ -2423,9 +2423,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001666", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz", - "integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==", + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "dev": true, "funding": [ { @@ -2709,9 +2709,9 @@ "license": "ISC" }, "node_modules/electron-to-chromium": { - "version": "1.5.31", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.31.tgz", - "integrity": "sha512-QcDoBbQeYt0+3CWcK/rEbuHvwpbT/8SV9T3OSgs6cX1FlcUAkgrkqbg9zLnDrMM/rLamzQwal4LYFCiWk861Tg==", + "version": "1.5.32", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", + "integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==", "dev": true, "license": "ISC" }, @@ -4025,22 +4025,22 @@ } }, "node_modules/tldts": { - "version": "6.1.49", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.49.tgz", - "integrity": "sha512-E5se9HuCyfwWvmc0JiXiocOw+Cm4tlJCKewdB5RKMH8MmtiTsQCc+yu5BBYB5ZN4lNbz8Xg65bqJ1odS9+RhIA==", + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", + "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.49" + "tldts-core": "^6.1.50" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.49", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.49.tgz", - "integrity": "sha512-ctRO/wzBasOCxAStJG/60Qe8/QpGmaVPsE8djdk0vioxN4uCOgKoveH71Qc2EOmVMIjVf0BjigI5p9ZDuLOygg==", + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", "dev": true, "license": "MIT" }, From 6c4276c37f4be7b794aac54529972f6818b9bc26 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 4 Oct 2024 09:26:52 +0200 Subject: [PATCH 35/38] v3.0.0-rc.48 --- package-lock.json | 16 ++++++++-------- package.json | 2 +- packages/extension-tei/package.json | 4 ++-- packages/text-annotator-react/package.json | 6 +++--- packages/text-annotator/package.json | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index c0c720c1..180d9f11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "license": "BSD-3-Clause", "workspaces": [ "./packages/text-annotator", @@ -4555,7 +4555,7 @@ }, "packages/extension-tei": { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "license": "BSD-3-Clause", "devDependencies": { "CETEIcean": "^1.9.3", @@ -4565,12 +4565,12 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.9", - "@recogito/text-annotator": "3.0.0-rc.47" + "@recogito/text-annotator": "3.0.0-rc.48" } }, "packages/text-annotator": { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.9", @@ -4594,14 +4594,14 @@ }, "packages/text-annotator-react": { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.9", "@annotorious/react": "^3.0.9", "@floating-ui/react": "^0.26.24", - "@recogito/text-annotator": "3.0.0-rc.47", - "@recogito/text-annotator-tei": "3.0.0-rc.47", + "@recogito/text-annotator": "3.0.0-rc.48", + "@recogito/text-annotator-tei": "3.0.0-rc.48", "CETEIcean": "^1.9.3" }, "devDependencies": { diff --git a/package.json b/package.json index 011e1c76..816f2de0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "description": "Recogito Text Annotator monorepo", "author": "Rainer Simon", "repository": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index 4c4afd6c..3aae6137 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "description": "Recogito Text Annotator TEI extension", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -33,6 +33,6 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.9", - "@recogito/text-annotator": "3.0.0-rc.47" + "@recogito/text-annotator": "3.0.0-rc.48" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index 6715aea9..0e4b0954 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "description": "Recogito Text Annotator React bindings", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -47,8 +47,8 @@ "@annotorious/core": "^3.0.9", "@annotorious/react": "^3.0.9", "@floating-ui/react": "^0.26.24", - "@recogito/text-annotator": "3.0.0-rc.47", - "@recogito/text-annotator-tei": "3.0.0-rc.47", + "@recogito/text-annotator": "3.0.0-rc.48", + "@recogito/text-annotator-tei": "3.0.0-rc.48", "CETEIcean": "^1.9.3" } } \ No newline at end of file diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index c96af286..9daec3e5 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.47", + "version": "3.0.0-rc.48", "description": "A JavaScript text annotation library", "author": "Rainer Simon", "license": "BSD-3-Clause", From c08f60c15cfa5a92bc36221883af4fec984bb9e8 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 4 Oct 2024 09:50:44 +0200 Subject: [PATCH 36/38] Tweaks --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 12 +++++++----- packages/text-annotator-react/test/index.html | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index 13bcdafd..ed2a4674 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -72,11 +72,13 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { useEffect(() => { setOpen( - // Selected annotation exists and has a selector + // Selected annotation exists and has a selector? annotation?.target.selector && - // The selector is not empty - use case: e.g. lazy loading PDF annotations, - // annotations created through plugins etc. - annotation.target.selector.length > 0 + // Selector not empty? (Annotations from plugins, general defensive programming) + annotation.target.selector.length > 0 && + // Range not collapsed? (E.g. lazy loading PDFs. Note that this will have to + // change if we switch from ranges to pre-computed bounds!) + !annotation.target.selector[0].range.collapsed ); }, [annotation]); @@ -133,7 +135,7 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { returnFocus={false} initialFocus={initialFocus}>
Date: Fri, 4 Oct 2024 09:53:17 +0200 Subject: [PATCH 37/38] v3.0.0-rc.49 --- package-lock.json | 16 ++++++++-------- package.json | 2 +- packages/extension-tei/package.json | 4 ++-- packages/text-annotator-react/package.json | 6 +++--- packages/text-annotator/package.json | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 180d9f11..ae2cdf55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "license": "BSD-3-Clause", "workspaces": [ "./packages/text-annotator", @@ -4555,7 +4555,7 @@ }, "packages/extension-tei": { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "license": "BSD-3-Clause", "devDependencies": { "CETEIcean": "^1.9.3", @@ -4565,12 +4565,12 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.9", - "@recogito/text-annotator": "3.0.0-rc.48" + "@recogito/text-annotator": "3.0.0-rc.49" } }, "packages/text-annotator": { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.9", @@ -4594,14 +4594,14 @@ }, "packages/text-annotator-react": { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "license": "BSD-3-Clause", "dependencies": { "@annotorious/core": "^3.0.9", "@annotorious/react": "^3.0.9", "@floating-ui/react": "^0.26.24", - "@recogito/text-annotator": "3.0.0-rc.48", - "@recogito/text-annotator-tei": "3.0.0-rc.48", + "@recogito/text-annotator": "3.0.0-rc.49", + "@recogito/text-annotator-tei": "3.0.0-rc.49", "CETEIcean": "^1.9.3" }, "devDependencies": { diff --git a/package.json b/package.json index 816f2de0..b1fcf1b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-monorepo", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "description": "Recogito Text Annotator monorepo", "author": "Rainer Simon", "repository": { diff --git a/packages/extension-tei/package.json b/packages/extension-tei/package.json index 3aae6137..b67ad3d4 100644 --- a/packages/extension-tei/package.json +++ b/packages/extension-tei/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator-tei", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "description": "Recogito Text Annotator TEI extension", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -33,6 +33,6 @@ }, "peerDependencies": { "@annotorious/core": "^3.0.9", - "@recogito/text-annotator": "3.0.0-rc.48" + "@recogito/text-annotator": "3.0.0-rc.49" } } \ No newline at end of file diff --git a/packages/text-annotator-react/package.json b/packages/text-annotator-react/package.json index 0e4b0954..f1f4eeaa 100644 --- a/packages/text-annotator-react/package.json +++ b/packages/text-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/react-text-annotator", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "description": "Recogito Text Annotator React bindings", "author": "Rainer Simon", "license": "BSD-3-Clause", @@ -47,8 +47,8 @@ "@annotorious/core": "^3.0.9", "@annotorious/react": "^3.0.9", "@floating-ui/react": "^0.26.24", - "@recogito/text-annotator": "3.0.0-rc.48", - "@recogito/text-annotator-tei": "3.0.0-rc.48", + "@recogito/text-annotator": "3.0.0-rc.49", + "@recogito/text-annotator-tei": "3.0.0-rc.49", "CETEIcean": "^1.9.3" } } \ No newline at end of file diff --git a/packages/text-annotator/package.json b/packages/text-annotator/package.json index 9daec3e5..fed72f8c 100644 --- a/packages/text-annotator/package.json +++ b/packages/text-annotator/package.json @@ -1,6 +1,6 @@ { "name": "@recogito/text-annotator", - "version": "3.0.0-rc.48", + "version": "3.0.0-rc.49", "description": "A JavaScript text annotation library", "author": "Rainer Simon", "license": "BSD-3-Clause", From 9ce6e881a4baf8f73b9d1dd47c1e39bdebcdd9d5 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 4 Oct 2024 10:12:35 +0200 Subject: [PATCH 38/38] Cleanup --- .../src/TextAnnotatorPopup/TextAnnotatorPopup.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx index ed2a4674..3a3272e0 100644 --- a/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx +++ b/packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx @@ -126,7 +126,7 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => { const onClose = () => r?.cancelSelected(); - return isOpen && selected.length > 0 ? ( + return isOpen && annotation ? ( { returnFocus={false} initialFocus={initialFocus}>