maidr 1.7.0__py3-none-any.whl → 1.7.2__py3-none-any.whl
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.
- maidr/__init__.py +1 -1
- maidr/core/maidr.py +46 -13
- maidr/core/plot/lineplot.py +8 -3
- maidr/util/mixin/extractor_mixin.py +54 -7
- {maidr-1.7.0.dist-info → maidr-1.7.2.dist-info}/METADATA +1 -1
- {maidr-1.7.0.dist-info → maidr-1.7.2.dist-info}/RECORD +8 -8
- {maidr-1.7.0.dist-info → maidr-1.7.2.dist-info}/WHEEL +0 -0
- {maidr-1.7.0.dist-info → maidr-1.7.2.dist-info}/licenses/LICENSE +0 -0
maidr/__init__.py
CHANGED
maidr/core/maidr.py
CHANGED
|
@@ -366,16 +366,29 @@ class Maidr:
|
|
|
366
366
|
iframe.contentWindow.document
|
|
367
367
|
) {{
|
|
368
368
|
let iframeDocument = iframe.contentWindow.document;
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
// Detect braille textarea by dynamic id prefix
|
|
370
|
+
let brailleContainer = iframeDocument.querySelector('[id^="maidr-braille-textarea"]');
|
|
371
|
+
// Detect review input container by class name
|
|
372
|
+
let reviewInputContainer = iframeDocument.querySelector('.maidr-review-input');
|
|
371
373
|
iframe.style.height = 'auto';
|
|
372
374
|
let height = iframeDocument.body.scrollHeight;
|
|
373
|
-
if
|
|
374
|
-
|
|
375
|
-
|
|
375
|
+
// Consider braille active if it or any descendant has focus
|
|
376
|
+
let isBrailleActive = brailleContainer && (
|
|
377
|
+
brailleContainer === iframeDocument.activeElement ||
|
|
378
|
+
(typeof brailleContainer.contains === 'function' && brailleContainer.contains(iframeDocument.activeElement))
|
|
379
|
+
);
|
|
380
|
+
// Consider review input active if it or any descendant has focus
|
|
381
|
+
let isReviewInputActive = reviewInputContainer && (
|
|
382
|
+
reviewInputContainer === iframeDocument.activeElement ||
|
|
383
|
+
(typeof reviewInputContainer.contains === 'function' && reviewInputContainer.contains(iframeDocument.activeElement))
|
|
384
|
+
);
|
|
385
|
+
// (logs removed)
|
|
386
|
+
if (isBrailleActive) {{
|
|
376
387
|
height += 100;
|
|
377
|
-
}}else{{
|
|
378
|
-
height += 50
|
|
388
|
+
}} else if (isReviewInputActive) {{
|
|
389
|
+
height += 50;
|
|
390
|
+
}} else {{
|
|
391
|
+
height += 50;
|
|
379
392
|
}}
|
|
380
393
|
iframe.style.height = (height) + 'px';
|
|
381
394
|
iframe.style.width = iframeDocument.body.scrollWidth + 'px';
|
|
@@ -387,12 +400,32 @@ class Maidr:
|
|
|
387
400
|
resizeIframe();
|
|
388
401
|
iframe.contentWindow.addEventListener('resize', resizeIframe);
|
|
389
402
|
}};
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
403
|
+
// Delegate focus events for braille textarea (by id prefix)
|
|
404
|
+
iframe.contentWindow.document.addEventListener('focusin', (e) => {{
|
|
405
|
+
try {{
|
|
406
|
+
const t = e && e.target ? e.target : null;
|
|
407
|
+
if (t && typeof t.id === 'string' && t.id.startsWith('maidr-braille-textarea')) resizeIframe();
|
|
408
|
+
}} catch (_) {{ resizeIframe(); }}
|
|
409
|
+
}}, true);
|
|
410
|
+
iframe.contentWindow.document.addEventListener('focusout', (e) => {{
|
|
411
|
+
try {{
|
|
412
|
+
const t = e && e.target ? e.target : null;
|
|
413
|
+
if (t && typeof t.id === 'string' && t.id.startsWith('maidr-braille-textarea')) resizeIframe();
|
|
414
|
+
}} catch (_) {{ resizeIframe(); }}
|
|
415
|
+
}}, true);
|
|
416
|
+
// Delegate focus events for review input container (by class name)
|
|
417
|
+
iframe.contentWindow.document.addEventListener('focusin', (e) => {{
|
|
418
|
+
try {{
|
|
419
|
+
const t = e && e.target ? e.target : null;
|
|
420
|
+
if (t && t.classList && t.classList.contains('maidr-review-input')) resizeIframe();
|
|
421
|
+
}} catch (_) {{ resizeIframe(); }}
|
|
422
|
+
}}, true);
|
|
423
|
+
iframe.contentWindow.document.addEventListener('focusout', (e) => {{
|
|
424
|
+
try {{
|
|
425
|
+
const t = e && e.target ? e.target : null;
|
|
426
|
+
if (t && t.classList && t.classList.contains('maidr-review-input')) resizeIframe();
|
|
427
|
+
}} catch (_) {{ resizeIframe(); }}
|
|
428
|
+
}}, true);
|
|
396
429
|
"""
|
|
397
430
|
return resizing_script
|
|
398
431
|
|
maidr/core/plot/lineplot.py
CHANGED
|
@@ -114,13 +114,18 @@ class MultiLinePlot(MaidrPlot, LineExtractorMixin):
|
|
|
114
114
|
elif not label.startswith("_child"):
|
|
115
115
|
line_type = label
|
|
116
116
|
|
|
117
|
+
# Use the new method to extract data with categorical labels
|
|
118
|
+
line_coords = LineExtractorMixin.extract_line_data_with_categorical_labels(self.ax, line)
|
|
119
|
+
if line_coords is None:
|
|
120
|
+
continue
|
|
121
|
+
|
|
117
122
|
line_data = [
|
|
118
123
|
{
|
|
119
|
-
MaidrKey.X:
|
|
120
|
-
MaidrKey.Y:
|
|
124
|
+
MaidrKey.X: x,
|
|
125
|
+
MaidrKey.Y: y,
|
|
121
126
|
**({MaidrKey.FILL: line_type} if line_type else {}),
|
|
122
127
|
}
|
|
123
|
-
for x, y in
|
|
128
|
+
for x, y in line_coords
|
|
124
129
|
]
|
|
125
130
|
|
|
126
131
|
if line_data:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
1
|
+
import numpy as np
|
|
2
|
+
from typing import Any, List, Optional, Tuple, Union
|
|
4
3
|
|
|
5
4
|
from matplotlib.axes import Axes
|
|
6
5
|
from matplotlib.cm import ScalarMappable
|
|
@@ -38,7 +37,7 @@ class ContainerExtractorMixin:
|
|
|
38
37
|
|
|
39
38
|
class LevelExtractorMixin:
|
|
40
39
|
@staticmethod
|
|
41
|
-
def extract_level(ax: Axes, key: MaidrKey = MaidrKey.X) ->
|
|
40
|
+
def extract_level(ax: Axes, key: MaidrKey = MaidrKey.X) -> Optional[List[str]]:
|
|
42
41
|
"""Retrieve label texts from Axes based on the specified Maidr key."""
|
|
43
42
|
if ax is None:
|
|
44
43
|
return None
|
|
@@ -95,7 +94,7 @@ class LevelExtractorMixin:
|
|
|
95
94
|
|
|
96
95
|
class LineExtractorMixin:
|
|
97
96
|
@staticmethod
|
|
98
|
-
def extract_line(ax: Axes) -> Line2D
|
|
97
|
+
def extract_line(ax: Axes) -> Optional[Line2D]:
|
|
99
98
|
"""Retrieve the last line object from Axes, if available."""
|
|
100
99
|
if ax is None or ax.get_lines() is None:
|
|
101
100
|
return None
|
|
@@ -105,7 +104,7 @@ class LineExtractorMixin:
|
|
|
105
104
|
return ax.get_lines()[-1]
|
|
106
105
|
|
|
107
106
|
@staticmethod
|
|
108
|
-
def extract_lines(ax: Axes) ->
|
|
107
|
+
def extract_lines(ax: Axes) -> Optional[List[Line2D]]:
|
|
109
108
|
"""Retrieve all line objects from Axes, if available."""
|
|
110
109
|
if ax is None or ax.get_lines() is None:
|
|
111
110
|
return None
|
|
@@ -114,6 +113,54 @@ class LineExtractorMixin:
|
|
|
114
113
|
# `maidr` package supports the same.
|
|
115
114
|
return ax.get_lines()
|
|
116
115
|
|
|
116
|
+
@staticmethod
|
|
117
|
+
def extract_line_data_with_categorical_labels(ax: Axes, line: Line2D) -> Optional[List[Tuple[Union[str, float], float]]]:
|
|
118
|
+
"""
|
|
119
|
+
Extract line data with proper handling of categorical x-axis labels.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
ax : Axes
|
|
124
|
+
The matplotlib axes object
|
|
125
|
+
line : Line2D
|
|
126
|
+
The line object to extract data from
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
Optional[List[Tuple[Union[str, float], float]]]
|
|
131
|
+
List of (x, y) tuples where x values are categorical labels if available,
|
|
132
|
+
or numeric values if no categorical labels are found
|
|
133
|
+
"""
|
|
134
|
+
if ax is None or line is None:
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
xydata = line.get_xydata()
|
|
138
|
+
if xydata is None:
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
# Convert to numpy array for easier handling
|
|
142
|
+
xy_array = np.asarray(xydata)
|
|
143
|
+
if xy_array.size == 0:
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
# Extract x-axis labels for categorical data
|
|
147
|
+
x_labels = LevelExtractorMixin.extract_level(ax, MaidrKey.X)
|
|
148
|
+
|
|
149
|
+
# If we have categorical labels, map numeric coordinates to labels
|
|
150
|
+
if x_labels:
|
|
151
|
+
result = []
|
|
152
|
+
for x, y in xy_array:
|
|
153
|
+
# Map numeric x-coordinate to categorical label if available
|
|
154
|
+
if isinstance(x, (int, float)) and 0 <= int(x) < len(x_labels):
|
|
155
|
+
x_value = x_labels[int(x)]
|
|
156
|
+
else:
|
|
157
|
+
x_value = float(x)
|
|
158
|
+
result.append((x_value, float(y)))
|
|
159
|
+
return result
|
|
160
|
+
else:
|
|
161
|
+
# No categorical labels, return numeric values
|
|
162
|
+
return [(float(x), float(y)) for x, y in xy_array]
|
|
163
|
+
|
|
117
164
|
|
|
118
165
|
class CollectionExtractorMixin:
|
|
119
166
|
@staticmethod
|
|
@@ -133,7 +180,7 @@ class CollectionExtractorMixin:
|
|
|
133
180
|
|
|
134
181
|
class ScalarMappableExtractorMixin:
|
|
135
182
|
@staticmethod
|
|
136
|
-
def extract_scalar_mappable(ax: Axes) -> ScalarMappable
|
|
183
|
+
def extract_scalar_mappable(ax: Axes) -> Optional[ScalarMappable]:
|
|
137
184
|
"""Retrieve the first collection ScalarMappable from an Axes object."""
|
|
138
185
|
if ax is None or ax.get_children() is None:
|
|
139
186
|
return None
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
maidr/__init__.py,sha256=
|
|
1
|
+
maidr/__init__.py,sha256=X3vZu1thIgth4Y8f6nQ4R_DeyWdCRvj_ukKAZ_7bPT0,415
|
|
2
2
|
maidr/api.py,sha256=gRNLXqUWpFGdD-I7Nu6J0_LeEni9KRAr0TBHwHaDAsc,1928
|
|
3
3
|
maidr/core/__init__.py,sha256=WgxLpSEYMc4k3OyEOf1shOxfEq0ASzppEIZYmE91ThQ,25
|
|
4
4
|
maidr/core/context_manager.py,sha256=6cT7ZGOApSpC-SLD2XZWWU_H08i-nfv-JUlzXOtvWYw,3374
|
|
5
5
|
maidr/core/figure_manager.py,sha256=jXs-Prkeru1Pahj21hjh8BAwXM9ZFUZ3GFfKUfIRX_M,4117
|
|
6
|
-
maidr/core/maidr.py,sha256=
|
|
6
|
+
maidr/core/maidr.py,sha256=cXSE3Cymd6XQVk77KmQhWRtuvAX3nPzV2ZxpolsPr7w,18408
|
|
7
7
|
maidr/core/enum/__init__.py,sha256=9ee78L0dlxEx4ulUGVlD-J23UcUZmrGu0rXms54up3c,93
|
|
8
8
|
maidr/core/enum/library.py,sha256=e8ujT_L-McJWfoVJd1ty9K_2bwITnf1j0GPLsnAcHes,104
|
|
9
9
|
maidr/core/enum/maidr_key.py,sha256=ljG0omqzd8K8Yk213N7i7PXGvG-IOlnE5v7o6RoGJzc,795
|
|
@@ -16,7 +16,7 @@ maidr/core/plot/candlestick.py,sha256=9R1ddSnUkGEE9WJgUPeuZhRtxXNBnOM9rbJdfJcY8b
|
|
|
16
16
|
maidr/core/plot/grouped_barplot.py,sha256=_zn4XMeEnSiDHtf6t4-z9ErBqg_CijhAS2CCtlHgYIQ,2077
|
|
17
17
|
maidr/core/plot/heatmap.py,sha256=yMS-31tS2GW4peds9LtZesMxmmTV_YfqYO5M_t5KasQ,2521
|
|
18
18
|
maidr/core/plot/histogram.py,sha256=QV5W-6ZJQQcZsrM91JJBX-ONktJzH7yg_et5_bBPfQQ,1525
|
|
19
|
-
maidr/core/plot/lineplot.py,sha256=
|
|
19
|
+
maidr/core/plot/lineplot.py,sha256=VbMjG-D5X-oeehduAtbqsyZ-hbcFc4NQYBwpCzgk4lo,4492
|
|
20
20
|
maidr/core/plot/maidr_plot.py,sha256=9T0boWaonM99jggEed97-rCy_cufRMWXrXo-CbmPudE,4230
|
|
21
21
|
maidr/core/plot/maidr_plot_factory.py,sha256=NW2iFScswgXbAC9rAOo4iMkAFsjY43DAvFioGr0yzx4,2732
|
|
22
22
|
maidr/core/plot/mplfinance_barplot.py,sha256=zhTp2i6BH0xn7vQvGTotKgu2HbzlKT4p6zA5CVUUHHc,5673
|
|
@@ -48,11 +48,11 @@ maidr/util/plot_detection.py,sha256=bgLHoDcHSRwOiyKzUK3EqGwdAIhF44ocHW5ox6xYGZw,
|
|
|
48
48
|
maidr/util/regression_line_utils.py,sha256=yFKr-H0whT_su2YVZwNksBLp5EC5s77sr6HUFgNcsyY,2329
|
|
49
49
|
maidr/util/svg_utils.py,sha256=2gyzBtNKFHs0utrw1iOlxTmznzivOWQMV2aW8zu2c8E,1442
|
|
50
50
|
maidr/util/mixin/__init__.py,sha256=aGJZNhtWh77yIVPc7ipIZm1OajigjMtCWYKPuDWTC-c,217
|
|
51
|
-
maidr/util/mixin/extractor_mixin.py,sha256=
|
|
51
|
+
maidr/util/mixin/extractor_mixin.py,sha256=l1DQTqZiVeZ18qXrz-rKCh8ETFofucBfwjIjO4S85HU,6923
|
|
52
52
|
maidr/util/mixin/merger_mixin.py,sha256=V0qLw_6DUB7X6CQ3BCMpsCQX_ZuwAhoSTm_E4xAJFKM,712
|
|
53
53
|
maidr/widget/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
maidr/widget/shiny.py,sha256=wrrw2KAIpE_A6CNQGBtNHauR1DjenA_n47qlFXX9_rk,745
|
|
55
|
-
maidr-1.7.
|
|
56
|
-
maidr-1.7.
|
|
57
|
-
maidr-1.7.
|
|
58
|
-
maidr-1.7.
|
|
55
|
+
maidr-1.7.2.dist-info/METADATA,sha256=8oaTlEpNVa5w8tBjKYofiFVj1h6Tn1fOAy54SyNZyz0,3154
|
|
56
|
+
maidr-1.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
57
|
+
maidr-1.7.2.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
58
|
+
maidr-1.7.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|