react-pdf-highlighter-plus 1.1.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,21 +13,21 @@
13
13
  }
14
14
 
15
15
  .PdfHighlighter::-webkit-scrollbar-thumb {
16
- background-color: #9f9f9f;
17
- border-radius: 5px;
16
+ background-color: var(--rphp-border-strong, #b7b3ab);
17
+ border-radius: 999px;
18
18
  }
19
19
 
20
20
  .PdfHighlighter::-webkit-scrollbar-thumb:hover {
21
- background-color: #d1d1d1;
21
+ background-color: var(--rphp-text-muted, #8b8880);
22
22
  }
23
23
 
24
24
  .PdfHighlighter::-webkit-scrollbar-track {
25
- background-color: #2c2c2c;
26
- border-radius: 5px;
25
+ background-color: transparent;
26
+ border-radius: 999px;
27
27
  }
28
28
 
29
29
  .PdfHighlighter::-webkit-scrollbar-track-piece {
30
- background-color: #2c2c2c;
30
+ background-color: transparent;
31
31
  }
32
32
 
33
33
  .PdfHighlighter__tip-container {
@@ -39,13 +39,19 @@
39
39
  position: absolute;
40
40
  inset: 0;
41
41
  z-index: 4;
42
+ /* Lives in .page as a sibling of .textLayer, not nested inside it — that
43
+ would scope our z-index to .textLayer's own local stacking context,
44
+ putting pdf.js's .annotationLayer (a .page-level sibling of .textLayer,
45
+ z-index 3) above our highlights globally and silently swallowing
46
+ clicks. Multiply is set explicitly here instead of inherited from
47
+ .textLayer: it's what makes a Text/Area highlight's color tint still
48
+ show the black text underneath (like a real highlighter pen) instead
49
+ of covering it. Opaque annotation types (Image/Drawing/Freetext/Shape)
50
+ render in .PdfHighlighter__note-layer instead, with normal blending. */
51
+ mix-blend-mode: multiply;
42
52
  pointer-events: none;
43
53
  }
44
54
 
45
- .textLayer > .PdfHighlighter__highlight-layer {
46
- z-index: 4;
47
- }
48
-
49
55
  .PdfHighlighter__note-layer {
50
56
  position: absolute;
51
57
  inset: 0;
@@ -123,24 +129,68 @@
123
129
  cursor: crosshair;
124
130
  }
125
131
 
126
- /* Dark mode - softer inversion for comfortable reading
127
- Uses 0.9 intensity by default for a dark gray (~#1a1a1a) instead of pure black.
128
- The brightness adjustment helps maintain readability.
129
- Note: These are fallback values - actual intensity is controlled via inline styles
130
- when darkModeInvertIntensity is customized in the theme prop. */
131
- .PdfHighlighter--dark .page {
132
- filter: invert(0.9) hue-rotate(180deg) brightness(1.05);
132
+ /* Dark mode recolors each page at draw time (OKLab map from theme.darkModeColors,
133
+ wired in PdfHighlighter). No CSS invert filter: inverting distorted photos and
134
+ colored text. Highlight/note/config layers render normally — they sit on
135
+ already-recolored pages, so no counter-inversion is needed. */
136
+
137
+ /* Dark mode: give every highlight a persistent accent border so they stay
138
+ legible against the recolored dark page (light mode keeps the ring on
139
+ scrolled-to only). :not(--scrolledTo) so the active highlight keeps its
140
+ stronger double ring (equal-specificity rules would otherwise clobber it by
141
+ load order). */
142
+ .PdfHighlighter--dark
143
+ .TextHighlight:not(.TextHighlight--scrolledTo)
144
+ .TextHighlight__part,
145
+ .PdfHighlighter--dark
146
+ .AreaHighlight:not(.AreaHighlight--scrolledTo)
147
+ .AreaHighlight__part {
148
+ box-shadow: 0 0 0 1px var(--rphp-accent, #7b71f0);
149
+ }
150
+
151
+ /* The text/highlight layer blends with the page canvas via `multiply`
152
+ (pdf_viewer.css). Over the dark recolored page that crushes highlights to
153
+ near-black, and `screen` washes them out (recolored text is already light, so
154
+ light highlight + light text = no contrast). Instead: normal blend, and make
155
+ the highlight FILLS translucent via --hl-fill-alpha (TextHighlight /
156
+ AreaHighlight read it through color-mix). Translucency comes from the fill
157
+ color, not element opacity, so the red border ring stays crisp. The light text
158
+ then reads on a muted colored tint — a proper dark-mode highlight. */
159
+ .PdfHighlighter--dark {
160
+ --hl-fill-alpha: 42%;
161
+ }
162
+ .PdfHighlighter--dark .textLayer {
163
+ mix-blend-mode: normal;
133
164
  }
134
-
135
- /* Double-invert highlights to preserve their original colors */
165
+ /* Our own highlight-layer sets multiply explicitly (it's a .page-level
166
+ sibling of .textLayer, not nested inside it see PdfHighlighter__
167
+ highlight-layer above), so it needs this same dark-mode override in its
168
+ own right; it no longer inherits .textLayer's override through nesting. */
136
169
  .PdfHighlighter--dark .PdfHighlighter__highlight-layer {
137
- filter: invert(0.9) hue-rotate(180deg) brightness(0.95);
170
+ mix-blend-mode: normal;
138
171
  }
139
172
 
140
- .PdfHighlighter--dark .PdfHighlighter__note-layer {
141
- filter: invert(0.9) hue-rotate(180deg) brightness(0.95);
173
+ /* Live text selection: the default opaque blue + multiply/screen makes selected
174
+ text unreadable on dark. Force a translucent selection with normal blend so
175
+ the light text shows through the highlight. */
176
+ .PdfHighlighter--dark .textLayer ::selection {
177
+ background: rgba(120, 162, 247, 0.4) !important;
178
+ mix-blend-mode: normal;
142
179
  }
143
-
144
- .PdfHighlighter--dark .PdfHighlighter__config-layer {
145
- filter: invert(0.9) hue-rotate(180deg) brightness(0.95);
180
+ .PdfHighlighter--dark .MouseSelection {
181
+ mix-blend-mode: normal;
182
+ opacity: 0.4;
183
+ }
184
+
185
+ /* Respect the OS "reduce motion" setting within the viewer (scoped so the
186
+ library doesn't override a consumer's whole app). */
187
+ @media (prefers-reduced-motion: reduce) {
188
+ .PdfHighlighter,
189
+ .PdfHighlighter *,
190
+ .PdfHighlighter *::before,
191
+ .PdfHighlighter *::after {
192
+ animation-duration: 0.01ms !important;
193
+ animation-iteration-count: 1 !important;
194
+ transition-duration: 0.01ms !important;
195
+ }
146
196
  }
@@ -6,7 +6,7 @@
6
6
  height: 100%;
7
7
  cursor: crosshair;
8
8
  z-index: 1000;
9
- background: rgba(0, 0, 0, 0.1);
9
+ background: rgba(28, 27, 24, 0.1);
10
10
  }
11
11
 
12
12
  .ShapeCanvas__controls {
@@ -19,29 +19,35 @@
19
19
  align-items: center;
20
20
  gap: 12px;
21
21
  z-index: 1002;
22
+ font-family: var(--rphp-font);
22
23
  }
23
24
 
25
+ /* Hint - dark ink pill */
24
26
  .ShapeCanvas__hint {
25
- background: rgba(0, 0, 0, 0.8);
26
- color: white;
27
+ background: var(--rphp-text, #1c1b18);
28
+ color: #efece5;
27
29
  padding: 8px 16px;
28
- border-radius: 6px;
29
- font-size: 14px;
30
+ border-radius: var(--rphp-radius, 9px);
31
+ box-shadow: var(--rphp-shadow-lg, 0 8px 24px -6px rgba(28, 27, 24, 0.22));
32
+ font-size: 13px;
33
+ font-family: var(--rphp-font);
30
34
  white-space: nowrap;
31
35
  }
32
36
 
37
+ /* Danger action */
33
38
  .ShapeCanvas__cancelButton {
34
- padding: 8px 20px;
35
- background: #f44336;
36
- color: white;
39
+ padding: 6px 14px;
40
+ background: transparent;
41
+ color: var(--rphp-danger, #ef4444);
37
42
  border: none;
38
- border-radius: 4px;
43
+ border-radius: var(--rphp-radius, 9px);
39
44
  cursor: pointer;
40
- font-size: 14px;
41
- font-weight: 500;
45
+ font-size: 13px;
46
+ font-weight: 600;
47
+ font-family: var(--rphp-font);
42
48
  transition: background 0.2s;
43
49
  }
44
50
 
45
51
  .ShapeCanvas__cancelButton:hover {
46
- background: #d32f2f;
52
+ background: rgba(239, 68, 68, 0.12);
47
53
  }
@@ -1,5 +1,6 @@
1
1
  .ShapeHighlight {
2
2
  position: absolute;
3
+ font-family: var(--rphp-font);
3
4
  }
4
5
 
5
6
  .ShapeHighlight__rnd {
@@ -21,11 +22,19 @@
21
22
  .ShapeHighlight--scrolledTo .ShapeHighlight__svg rect,
22
23
  .ShapeHighlight--scrolledTo .ShapeHighlight__svg ellipse,
23
24
  .ShapeHighlight--scrolledTo .ShapeHighlight__svg line {
24
- stroke: #ff4141 !important;
25
+ stroke: var(--rphp-accent, #5b50e6) !important;
25
26
  }
26
27
 
27
28
  .ShapeHighlight--scrolledTo .ShapeHighlight__svg polygon {
28
- fill: #ff4141 !important;
29
+ fill: var(--rphp-accent, #5b50e6) !important;
30
+ }
31
+
32
+ /* Selected: accent ring on the shape's bounding box */
33
+ .ShapeHighlight--selected .ShapeHighlight__container {
34
+ box-shadow:
35
+ 0 0 0 2px var(--rphp-accent, #5b50e6),
36
+ 0 0 0 5px rgba(91, 80, 230, 0.25);
37
+ border-radius: 2px;
29
38
  }
30
39
 
31
40
  /* Toolbar wrapper - creates hover bridge between toolbar and shape */
@@ -33,22 +42,76 @@
33
42
  z-index: 10;
34
43
  }
35
44
 
36
- /* Toolbar - appears on hover */
45
+ /* Toolbar - dark ink pill floating ABOVE the shape (never covers it).
46
+ Shown on hover or while the shape is selected. */
37
47
  .ShapeHighlight__toolbar {
38
48
  display: flex;
39
49
  align-items: center;
40
- gap: 4px;
41
- padding: 2px 4px;
42
- background: rgba(0, 0, 0, 0.7);
43
- border-radius: 4px;
50
+ gap: 2px;
51
+ padding: 4px 6px;
52
+ background: var(--rphp-toolbar-bg, #1c1b18);
53
+ border-radius: var(--rphp-radius, 9px);
54
+ box-shadow: var(--rphp-shadow-lg, 0 8px 24px -6px rgba(28, 27, 24, 0.22));
55
+ position: absolute;
56
+ bottom: calc(100% + 6px);
57
+ left: 0;
44
58
  opacity: 0;
45
59
  pointer-events: none;
46
- transition: opacity 0.2s ease;
60
+ transition: opacity 0.15s ease, transform 0.15s ease;
61
+ transform: translateY(2px);
62
+ white-space: nowrap;
63
+ }
64
+
65
+ /* Hover bridge across the 6px gap between toolbar and shape */
66
+ .ShapeHighlight__toolbar::after {
67
+ content: "";
68
+ position: absolute;
69
+ top: 100%;
70
+ left: 0;
71
+ right: 0;
72
+ height: 10px;
47
73
  }
48
74
 
49
75
  .ShapeHighlight__toolbar--visible {
50
76
  opacity: 1;
51
77
  pointer-events: auto;
78
+ transform: translateY(0);
79
+ }
80
+
81
+ /* Color dropdown trigger: current-color swatch + chevron */
82
+ .ShapeHighlight__color-trigger {
83
+ display: flex;
84
+ align-items: center;
85
+ gap: 4px;
86
+ height: 26px;
87
+ padding: 0 6px 0 4px;
88
+ border: none;
89
+ background: transparent;
90
+ cursor: pointer;
91
+ color: #efece5;
92
+ border-radius: var(--rphp-radius-sm, 6px);
93
+ transition: background 0.15s, color 0.15s;
94
+ }
95
+
96
+ .ShapeHighlight__color-trigger:hover,
97
+ .ShapeHighlight__color-trigger[aria-expanded="true"] {
98
+ background: rgba(255, 255, 255, 0.14);
99
+ color: #ffffff;
100
+ }
101
+
102
+ .ShapeHighlight__color-trigger-dot {
103
+ width: 14px;
104
+ height: 14px;
105
+ border-radius: 50%;
106
+ border: 1.5px solid rgba(255, 255, 255, 0.5);
107
+ flex-shrink: 0;
108
+ }
109
+
110
+ .ShapeHighlight__toolbar-divider {
111
+ width: 1px;
112
+ height: 16px;
113
+ margin: 0 3px;
114
+ background: rgba(255, 255, 255, 0.2);
52
115
  }
53
116
 
54
117
  .ShapeHighlight__style-button,
@@ -56,40 +119,43 @@
56
119
  display: flex;
57
120
  align-items: center;
58
121
  justify-content: center;
59
- width: 20px;
60
- height: 20px;
122
+ width: 26px;
123
+ height: 26px;
61
124
  border: none;
62
125
  background: transparent;
63
126
  cursor: pointer;
64
- color: white;
65
- border-radius: 3px;
127
+ color: #efece5;
128
+ border-radius: var(--rphp-radius-sm, 6px);
66
129
  padding: 0;
67
- transition: background 0.2s;
130
+ transition: background 0.15s, color 0.15s;
68
131
  }
69
132
 
70
133
  .ShapeHighlight__style-button:hover {
71
- background: rgba(255, 255, 255, 0.2);
134
+ background: rgba(255, 255, 255, 0.14);
135
+ color: #ffffff;
72
136
  }
73
137
 
74
138
  .ShapeHighlight__delete-button:hover {
75
- background: rgba(255, 100, 100, 0.6);
139
+ background: rgba(239, 68, 68, 0.24);
140
+ color: #ff8a80;
76
141
  }
77
142
 
78
- /* Style Panel */
143
+ /* Style Panel - light surface card (Verso popover) */
79
144
  .ShapeHighlight__style-panel {
80
- margin-top: 4px;
81
- background: rgba(0, 0, 0, 0.9);
82
- border-radius: 6px;
83
- padding: 8px;
145
+ margin-top: 6px;
146
+ background: var(--rphp-surface, #ffffff);
147
+ border: 1px solid var(--rphp-border, #e6e2da);
148
+ border-radius: var(--rphp-radius-lg, 12px);
149
+ padding: 12px;
84
150
  min-width: 180px;
85
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
151
+ box-shadow: var(--rphp-shadow-lg, 0 8px 24px -6px rgba(28, 27, 24, 0.22));
86
152
  }
87
153
 
88
154
  .ShapeHighlight__style-row {
89
155
  display: flex;
90
156
  align-items: center;
91
157
  justify-content: space-between;
92
- margin-bottom: 8px;
158
+ margin-bottom: 10px;
93
159
  }
94
160
 
95
161
  .ShapeHighlight__style-row:last-child {
@@ -97,60 +163,63 @@
97
163
  }
98
164
 
99
165
  .ShapeHighlight__style-row label {
100
- color: #ccc;
101
- font-size: 11px;
166
+ color: var(--rphp-text-muted, #8b8880);
167
+ font-size: 10px;
168
+ font-weight: 600;
102
169
  text-transform: uppercase;
103
- letter-spacing: 0.5px;
104
- margin-right: 8px;
105
- }
106
-
107
- /* Color options */
108
- .ShapeHighlight__color-options {
170
+ letter-spacing: 0.8px;
171
+ margin-right: 10px;
172
+ }
173
+
174
+ /* Color dropdown menu - same slot/positioning as the style panel */
175
+ .ShapeHighlight__color-menu {
176
+ margin-top: 6px;
177
+ width: 180px;
178
+ background: var(--rphp-surface, #ffffff);
179
+ border: 1px solid var(--rphp-border, #e6e2da);
180
+ border-radius: var(--rphp-radius-lg, 12px);
181
+ box-shadow: var(--rphp-shadow-lg, 0 8px 24px -6px rgba(28, 27, 24, 0.22));
182
+ padding: 6px;
109
183
  display: flex;
110
- align-items: center;
111
- gap: 6px;
184
+ flex-direction: column;
185
+ gap: 1px;
112
186
  }
113
187
 
114
- .ShapeHighlight__color-presets {
188
+ .ShapeHighlight__color-menu-item {
115
189
  display: flex;
116
- gap: 4px;
117
- }
118
-
119
- .ShapeHighlight__color-preset {
120
- width: 18px;
121
- height: 18px;
122
- border: 2px solid transparent;
123
- border-radius: 50%;
190
+ align-items: center;
191
+ gap: 10px;
192
+ width: 100%;
193
+ padding: 7px 8px;
194
+ border: none;
195
+ background: transparent;
196
+ border-radius: var(--rphp-radius-sm, 6px);
124
197
  cursor: pointer;
125
- transition: transform 0.2s, border-color 0.2s;
126
- padding: 0;
127
- }
128
-
129
- .ShapeHighlight__color-preset:hover {
130
- transform: scale(1.15);
198
+ color: var(--rphp-text, #1c1b18);
199
+ font-size: 13px;
200
+ text-align: left;
131
201
  }
132
202
 
133
- .ShapeHighlight__color-preset.active {
134
- border-color: #b958ff;
203
+ .ShapeHighlight__color-menu-item:hover {
204
+ background: var(--rphp-surface-alt, #f4f2ee);
135
205
  }
136
206
 
137
- .ShapeHighlight__color-options input[type="color"] {
138
- width: 24px;
139
- height: 24px;
140
- padding: 0;
141
- border: none;
142
- border-radius: 4px;
143
- cursor: pointer;
144
- background: transparent;
207
+ .ShapeHighlight__color-menu-dot {
208
+ width: 16px;
209
+ height: 16px;
210
+ border-radius: 50%;
211
+ border: 1px solid var(--rphp-border, #e6e2da);
212
+ flex-shrink: 0;
145
213
  }
146
214
 
147
- .ShapeHighlight__color-options input[type="color"]::-webkit-color-swatch-wrapper {
148
- padding: 0;
215
+ .ShapeHighlight__color-menu-label {
216
+ flex: 1;
149
217
  }
150
218
 
151
- .ShapeHighlight__color-options input[type="color"]::-webkit-color-swatch {
152
- border: 1px solid #666;
153
- border-radius: 4px;
219
+ .ShapeHighlight__color-menu-check {
220
+ display: flex;
221
+ color: var(--rphp-accent, #5b50e6);
222
+ flex-shrink: 0;
154
223
  }
155
224
 
156
225
  /* Stroke width options */
@@ -161,22 +230,23 @@
161
230
 
162
231
  .ShapeHighlight__width-button {
163
232
  padding: 4px 8px;
164
- background: transparent;
165
- border: 1px solid #666;
166
- border-radius: 4px;
233
+ background: var(--rphp-surface-alt, #f4f2ee);
234
+ border: 1px solid var(--rphp-border, #e6e2da);
235
+ border-radius: var(--rphp-radius-sm, 6px);
167
236
  cursor: pointer;
168
- color: #ccc;
237
+ color: var(--rphp-text-secondary, #57544d);
169
238
  font-size: 11px;
170
- transition: all 0.2s;
239
+ font-family: var(--rphp-font);
240
+ transition: all 0.15s;
171
241
  }
172
242
 
173
243
  .ShapeHighlight__width-button:hover {
174
- border-color: #b958ff;
175
- color: white;
244
+ border-color: var(--rphp-accent, #5b50e6);
245
+ color: var(--rphp-accent, #5b50e6);
176
246
  }
177
247
 
178
248
  .ShapeHighlight__width-button.active {
179
- background: rgba(185, 88, 255, 0.2);
180
- border-color: #b958ff;
181
- color: #b958ff;
249
+ background: var(--rphp-accent-soft, #eceaf9);
250
+ border-color: var(--rphp-accent, #5b50e6);
251
+ color: var(--rphp-accent, #5b50e6);
182
252
  }