Dash_tooltip 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. dash_tooltip-0.5.0/.gitattributes +2 -0
  2. dash_tooltip-0.5.0/.github/workflows/Pytest.yml +39 -0
  3. dash_tooltip-0.5.0/.github/workflows/codeql.yml +38 -0
  4. dash_tooltip-0.5.0/.gitignore +154 -0
  5. dash_tooltip-0.5.0/.pre-commit-config.yaml +47 -0
  6. dash_tooltip-0.5.0/.python-version +1 -0
  7. dash_tooltip-0.5.0/Dash_tooltip.egg-info/PKG-INFO +301 -0
  8. dash_tooltip-0.5.0/Dash_tooltip.egg-info/SOURCES.txt +39 -0
  9. dash_tooltip-0.5.0/Dash_tooltip.egg-info/dependency_links.txt +1 -0
  10. dash_tooltip-0.5.0/Dash_tooltip.egg-info/requires.txt +2 -0
  11. dash_tooltip-0.5.0/Dash_tooltip.egg-info/top_level.txt +1 -0
  12. dash_tooltip-0.5.0/LICENSE +21 -0
  13. dash_tooltip-0.5.0/PKG-INFO +301 -0
  14. dash_tooltip-0.5.0/README.md +278 -0
  15. dash_tooltip-0.5.0/dash_qt_demo.py +165 -0
  16. dash_tooltip-0.5.0/dash_qt_demo2.py +200 -0
  17. dash_tooltip-0.5.0/dash_tooltip/__init__.py +267 -0
  18. dash_tooltip-0.5.0/dash_tooltip/_version.py +21 -0
  19. dash_tooltip-0.5.0/dash_tooltip/config.py +18 -0
  20. dash_tooltip-0.5.0/dash_tooltip/custom_figure.py +12 -0
  21. dash_tooltip-0.5.0/dash_tooltip/utils.py +324 -0
  22. dash_tooltip-0.5.0/dash_tooltip_demo.py +1328 -0
  23. dash_tooltip-0.5.0/pyproject.toml +88 -0
  24. dash_tooltip-0.5.0/setup.cfg +4 -0
  25. dash_tooltip-0.5.0/tests/__init__.py +0 -0
  26. dash_tooltip-0.5.0/tests/test_11_direct_figure_in_dcc_graph.py +120 -0
  27. dash_tooltip-0.5.0/tests/test_12_go_scatter.py +101 -0
  28. dash_tooltip-0.5.0/tests/test_13_go_scatter_line.py +106 -0
  29. dash_tooltip-0.5.0/tests/test_14_go_bar_chart.py +99 -0
  30. dash_tooltip-0.5.0/tests/test_16_update_template.py +116 -0
  31. dash_tooltip-0.5.0/tests/test_17_annotation_relayout_persistence.py +68 -0
  32. dash_tooltip-0.5.0/tests/test_1_tooltip_function.py +111 -0
  33. dash_tooltip-0.5.0/tests/test_2_tooltip_configuration.py +144 -0
  34. dash_tooltip-0.5.0/tests/test_3_template_formating.py +155 -0
  35. dash_tooltip-0.5.0/tests/test_4a_multiple_graph.py +93 -0
  36. dash_tooltip-0.5.0/tests/test_4b_multiple_graph.py +160 -0
  37. dash_tooltip-0.5.0/tests/test_6_invalid_graph_id.py +15 -0
  38. dash_tooltip-0.5.0/tests/test_7_tooltip_removal.py +152 -0
  39. dash_tooltip-0.5.0/tests/test_8__display_click_data.py +292 -0
  40. dash_tooltip-0.5.0/tests/test_dummy.py +2 -0
  41. dash_tooltip-0.5.0/uv.lock +12303 -0
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
@@ -0,0 +1,39 @@
1
+ name: Pytest
2
+
3
+ on:
4
+ push: {}
5
+ pull_request: {}
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ test:
10
+ name: Python ${{ matrix.python-version }}
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v5
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v6
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Set up uv
28
+ uses: astral-sh/setup-uv@v8
29
+ with:
30
+ enable-cache: true
31
+
32
+ - name: Install dependencies
33
+ run: uv sync --group dev
34
+
35
+ - name: Run Ruff
36
+ run: uv run ruff check . --output-format=github
37
+
38
+ - name: Run Pytest
39
+ run: uv run pytest tests/ -k "not selenium"
@@ -0,0 +1,38 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ branches: ["main"]
8
+ schedule:
9
+ - cron: "27 1 * * 4"
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ analyze:
14
+ name: Analyze Python
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ actions: read
18
+ contents: read
19
+ security-events: write
20
+
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ language: ["python"]
25
+
26
+ steps:
27
+ - name: Checkout repository
28
+ uses: actions/checkout@v5
29
+
30
+ - name: Initialize CodeQL
31
+ uses: github/codeql-action/init@v4
32
+ with:
33
+ languages: ${{ matrix.language }}
34
+
35
+ - name: Perform CodeQL Analysis
36
+ uses: github/codeql-action/analyze@v4
37
+ with:
38
+ category: "/language:${{ matrix.language }}"
@@ -0,0 +1,154 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
105
+ __pypackages__/
106
+
107
+ # Celery stuff
108
+ celerybeat-schedule
109
+ celerybeat.pid
110
+
111
+ # SageMath parsed files
112
+ *.sage.py
113
+
114
+ # Environments
115
+ .env
116
+ .venv
117
+ venv/
118
+ ENV/
119
+ venv.bak/
120
+ env*/
121
+
122
+ # Spyder project settings
123
+ .spyderproject
124
+ .spyproject
125
+
126
+ # Rope project settings
127
+ .ropeproject
128
+
129
+ # mkdocs documentation
130
+ /site
131
+
132
+ # mypy
133
+ .mypy_cache/
134
+ .dmypy.json
135
+ dmypy.json
136
+
137
+ # Pyre type checker
138
+ .pyre/
139
+
140
+ # pytype static type analyzer
141
+ .pytype/
142
+
143
+ # Cython debug symbols
144
+ cython_debug/
145
+
146
+ # PyCharm
147
+ # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
148
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
149
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
150
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
151
+ .idea/
152
+ *.ipynb
153
+
154
+ *.bat
@@ -0,0 +1,47 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: ruff
5
+ name: ruff
6
+ description: "Run 'ruff' for extremely fast Python linting"
7
+ entry: ruff check --fix --force-exclude
8
+ language: python
9
+ types_or: [python, pyi]
10
+ args: []
11
+ require_serial: true
12
+ additional_dependencies: []
13
+ minimum_pre_commit_version: "2.9.2"
14
+
15
+ - id: ruff-format
16
+ name: ruff-format
17
+ description: "Run 'ruff format' for extremely fast Python formatting"
18
+ entry: ruff format --force-exclude
19
+ language: python
20
+ types_or: [python, pyi]
21
+ args: []
22
+ require_serial: true
23
+ additional_dependencies: []
24
+ minimum_pre_commit_version: "2.9.2"
25
+
26
+ # - id: mypy
27
+ # name: mypy
28
+ # description: "Run mypy for static type checking"
29
+ # entry: mypy
30
+ # language: system
31
+ # types: [python]
32
+
33
+ - id: pytest-selenium
34
+ name: pytest (selenium tests)
35
+ description: "Run pytest for selenium tests"
36
+ entry: pytest
37
+ args: ['tests/', '-k', 'selenium', '--webdriver', 'Firefox', '--testmon']
38
+ language: system
39
+ pass_filenames: false
40
+
41
+ - id: pytest-non-selenium
42
+ name: pytest (non-selenium tests)
43
+ description: "Run pytest for non-selenium tests"
44
+ entry: pytest
45
+ args: ['tests/', '-k', 'not selenium', '--testmon']
46
+ language: system
47
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ 3.14.5
@@ -0,0 +1,301 @@
1
+ Metadata-Version: 2.4
2
+ Name: Dash_tooltip
3
+ Version: 0.5.0
4
+ Summary: A tooltip functionality for Dash.
5
+ Author: kb-
6
+ Project-URL: Homepage, https://github.com/kb-/Dash_tooltip
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.7
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Requires-Python: >=3.7
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: dash>=2.13.0
21
+ Requires-Dist: plotly>=5.17.0
22
+ Dynamic: license-file
23
+
24
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dash-tooltip)
25
+ [![CodeQL](https://github.com/kb-/Dash_tooltip/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/kb-/Dash_tooltip/actions/workflows/codeql.yml)
26
+ [![Downloads](https://static.pepy.tech/badge/dash_tooltip)](https://pepy.tech/project/dash_tooltip)
27
+ [![Pytest](https://github.com/kb-/Dash_tooltip/actions/workflows/Pytest.yml/badge.svg)](https://github.com/kb-/Dash_tooltip/actions/workflows/Pytest.yml)
28
+
29
+ # Dash Tooltip
30
+
31
+ A module to add interactive editable tooltips to your Dash applications. Inspired by `mplcursors` and Matlab's `datatip`.
32
+
33
+ ![newplot(6)](https://github.com/kb-/Dash_tooltip/assets/2260417/0d62008c-25f2-4128-aa31-6746b6b82248)
34
+
35
+ ## Installation
36
+
37
+ `pip install dash-tooltip`
38
+
39
+ ## Build And Publish
40
+
41
+ With the current `pyproject.toml`-based setup, use `uv` for local builds and publishing:
42
+
43
+ ```bash
44
+ # Build source distribution and wheel into dist/
45
+ uv build
46
+
47
+ # Install the built wheel locally
48
+ uv pip install dist/*.whl
49
+
50
+ # Publish to PyPI
51
+ uv publish
52
+ ```
53
+
54
+ ## Basic Usage
55
+
56
+ ```python
57
+ import numpy as np
58
+ import plotly.express as px
59
+ from dash import Dash, dcc, html
60
+ from dash.dependencies import Input, Output
61
+ from dash_tooltip import tooltip
62
+
63
+ # Sample Data
64
+ np.random.seed(20)
65
+ y1 = np.random.normal(0, 10, 50)
66
+ x1 = np.arange(0, 50)
67
+ fig1 = px.scatter(x=x1, y=y1)
68
+ fig1.update_layout(title_text="Editable Title", title_x=0.5)
69
+
70
+ app1 = Dash(__name__)
71
+
72
+ #makes graph items, including tooltips editable
73
+ app1.layout = html.Div([
74
+ dcc.Graph(
75
+ id='graph1',
76
+ figure=fig1,
77
+ config={
78
+ 'editable': True,
79
+ 'edits': {
80
+ 'shapePosition': True,
81
+ 'annotationPosition': True
82
+ }
83
+ }
84
+ )
85
+ ])
86
+
87
+ # Add the tooltip functionality to the app
88
+ tooltip(app1)
89
+ ```
90
+ Click on data points to add tooltips.
91
+ If `dcc.Graph` is configured editatble, tolltips:
92
+ - can be dragged around
93
+ - text can be edited on click
94
+ - can be deleted: click, delete text, enter. In some occasions a tooltip arrow may remain due to a Dash bug (clientside_callback not firing). In this cas, click near arrow end (mouse cursor changes to pointer), enter some text and repeat deletion and enter.
95
+
96
+
97
+ ## Advanced Usage
98
+
99
+ If you want to customize the tooltips, hover templates, and more:
100
+
101
+ ```python
102
+ import pandas as pd
103
+ import numpy as np
104
+ import plotly.express as px
105
+ from dash import Dash, dcc, html
106
+ from dash.dependencies import Input, Output
107
+ from dash_tooltip import tooltip
108
+
109
+ # Generate random time series data
110
+ date_rng = pd.date_range(start='2020-01-01', end='2020-12-31', freq='h')
111
+ ts1 = pd.Series(np.random.randn(len(date_rng)), index=date_rng, name='Time Series 1')
112
+ ts2 = pd.Series(np.random.randn(len(date_rng)), index=date_rng, name='Time Series 2')
113
+ df = pd.DataFrame({ts1.name: ts1, ts2.name: ts2})
114
+
115
+ # Define the hover and tooltip template
116
+ # name is only compatible with tooltip
117
+ template = "name:%{name}<br>META0: %{meta[0]}<br>META1: %{meta[1]}<br>x: %{x}<br>y: %{y:.2f}<br>pointNumber: %{pointNumber}<br>customdata0: %{customdata[0]}<br>customdata1: %{customdata[1]}"
118
+
119
+ # Create a line plot
120
+ fig10 = px.line(df, x=df.index, y=df.columns, title="Time Series Plot")
121
+
122
+ # Apply metadata and custom data to each trace
123
+ for i, trace in enumerate(fig10.data):
124
+ # Applying different metadata to each trace
125
+ trace.meta = [f"META{i}0", f"META{i}1"]
126
+
127
+ # Setting customdata for each point in the trace, for use in the hover template
128
+ trace.customdata = np.array([[f"Series {i+1}", f'Point {j+1}'] for j in range(len(df))])
129
+
130
+ # Setting the hover template
131
+ trace.hovertemplate = template
132
+
133
+ app10 = Dash(__name__)
134
+
135
+ app10.layout = html.Div([
136
+ dcc.Graph(
137
+ id="graph-id",
138
+ figure=fig10,
139
+ config={
140
+ 'editable': True,
141
+ 'edits': {
142
+ 'shapePosition': True,
143
+ 'annotationPosition': True
144
+ }
145
+ }
146
+ )
147
+ ])
148
+
149
+ tooltip(app10, graph_ids=["graph-id"], template=template, debug=True)
150
+ app10.run(port=8082)
151
+ ```
152
+
153
+ ## Tooltip Templates with Formatting
154
+
155
+ Tooltips can be formatted using templates similar to Plotly's hovertemplates. The tooltip template allows custom formatting and the inclusion of text and values.
156
+
157
+ For example, you can use a template like `"%{name}<br>%{meta[0]}<br>x: %{x:.2f}<br>y: %{y:.2f}"` to display the track `name`, `meta[0]` from a list of text data, plus `x` and `y` values with two decimal places. Note that `name` key is not available in the Plotly hover template, but is displayed by default.
158
+
159
+ Refer to [Plotly’s documentation on hover text and formatting](https://plotly.com/python/hover-text-and-formatting/) for more details on how to construct and customize your tooltip templates.
160
+
161
+ ## Custom Styling
162
+
163
+ ```python
164
+ custom_style = {
165
+ "font": {"size": 12, "color":"red"},
166
+ "arrowcolor": "red",
167
+ 'arrowsize': 5,
168
+ # ... any other customization
169
+ }
170
+ tooltip(app10, style=custom_style, graph_ids=["graph-id"], template=template, debug=True)
171
+ ```
172
+
173
+ For more examples, refer to the provided `dash_tooltip_demo.py` and check out [Plotly’s Text and Annotations documentation](https://plotly.com/python/text-and-annotations/#styling-and-coloring-annotations), which provides a wealth of information on customizing the appearance of annotations.
174
+ Refer to the [Plotly Annotation Reference](https://plotly.com/python/reference/layout/annotations/) for a comprehensive guide on available styling attributes and how to apply them.
175
+
176
+ ## Template updating
177
+
178
+ Tooltip content can be updated to match with selected data in a dynamic Dash app:
179
+ ```python
180
+ GRAPH_ID = "scatter-plot16a"
181
+
182
+ # Sample DataFrame with DatetimeIndex
183
+ date_range = pd.date_range(start="2025-01-01", periods=5)
184
+ df = pd.DataFrame(
185
+ {
186
+ "x": [1, 2, 3, 4, 5],
187
+ "y": [2, 4, 6, 8, 10],
188
+ "z": [3, 6, 9, 12, 15],
189
+ "a": [4, 8, 12, 16, 20],
190
+ "b": [5, 10, 15, 20, 25],
191
+ },
192
+ index=date_range,
193
+ )
194
+
195
+ # Initialize the Dash app
196
+ app16 = dash.Dash(__name__)
197
+
198
+ # Define the layout
199
+ app16.layout = html.Div(
200
+ [
201
+ html.Label("Select X and Y columns:"),
202
+ dcc.Dropdown(
203
+ id="x-column",
204
+ options=[{"label": col, "value": col} for col in df.columns],
205
+ placeholder="Select X axis data",
206
+ ),
207
+ dcc.Dropdown(
208
+ id="y-column",
209
+ options=[{"label": col, "value": col} for col in df.columns],
210
+ placeholder="Select Y axis data",
211
+ ),
212
+ dcc.Graph(
213
+ id=GRAPH_ID,
214
+ style={"width": "600px", "height": "600px"},
215
+ config={
216
+ "editable": True,
217
+ "edits": {"shapePosition": True, "annotationPosition": True},
218
+ },
219
+ ),
220
+ ]
221
+ )
222
+
223
+ # Create a tooltip instance
224
+ tooltip_instance16 = tooltip(app16, graph_ids=[GRAPH_ID])
225
+
226
+ # Define callback to update the scatter plot
227
+ @app16.callback(
228
+ Output(GRAPH_ID, "figure", allow_duplicate=True),
229
+ [Input("x-column", "value"), Input("y-column", "value")],
230
+ prevent_initial_call=True,
231
+ )
232
+ def update_scatter_plot(x_column, y_column):
233
+ if not x_column or not y_column:
234
+ raise PreventUpdate # Prevent update if either dropdown is not selected
235
+
236
+ non_selected_columns = [
237
+ col for col in df.columns if col not in [x_column, y_column]
238
+ ]
239
+ customdata = df[non_selected_columns].apply(
240
+ lambda row: "<br>".join(
241
+ f"{col}: {val}" for col, val in zip(non_selected_columns, row)
242
+ ),
243
+ axis=1,
244
+ )
245
+ # gives (depending on selected entries):
246
+ # 2022-01-01 x: 1<br>z: 3<br>b: 5
247
+ # 2022-01-02 x: 2<br>z: 6<br>b: 10
248
+ # ...
249
+
250
+ # New template, to match selected data entries
251
+ template = (
252
+ "<b>Date</b>: %{customdata}<br>"
253
+ + f"<b>{x_column}: %{{x}}<br>"
254
+ + f"{y_column}: %{{y}}</b><br>"
255
+ )
256
+ # gives (depending on selected entries):
257
+ # <b>Date</b>: %{customdata}<br><b>x: %{x}<br><b>a</b>: %{y}<br>
258
+
259
+ # Update template for new tooltips
260
+ tooltip_instance16.update_template(graph_id=GRAPH_ID, template=template)
261
+
262
+ trace = go.Scatter(
263
+ x=df[x_column],
264
+ y=df[y_column],
265
+ mode="markers",
266
+ marker=dict(color="blue"),
267
+ customdata=df.index.strftime("%Y-%m-%d %H:%M:%S") + "<br>" + customdata,
268
+ # Include date and time with other data
269
+ hovertemplate=template,
270
+ )
271
+ layout = go.Layout(
272
+ title="Scatter Plot",
273
+ xaxis=dict(title=x_column),
274
+ yaxis=dict(title=y_column),
275
+ hovermode="closest",
276
+ height=800,
277
+ width=800,
278
+ )
279
+ return {"data": [trace], "layout": layout}
280
+
281
+
282
+ # Run the app
283
+ if __name__ == "__main__":
284
+ app16.run(debug=False, port=8196)
285
+ ```
286
+
287
+ ## Handling Log Axes
288
+
289
+ Due to a long-standing bug in Plotly (see [Plotly Issue #2580](https://github.com/plotly/plotly.py/issues/2580)), annotations (`fig.add_annotation`) may not be placed correctly on log-scaled axes. The `dash_tooltip` module provides an option to automatically correct the tooltip placement on log-scaled axes via the `apply_log_fix` argument in the `tooltip` function. By default, `apply_log_fix` is set to `True` to enable the fix.
290
+
291
+ ## Debugging
292
+
293
+ If you encounter any issues or unexpected behaviors, enable the debug mode by setting the `debug` argument of the `tooltip` function to `True`. The log outputs will be written to `dash_app.log` in the directory where your script or application is located.
294
+
295
+ ## License
296
+
297
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
298
+
299
+ ## Acknowledgements
300
+
301
+ - Inspired by `mplcursors` and Matlab's `datatip`.
@@ -0,0 +1,39 @@
1
+ .gitattributes
2
+ .gitignore
3
+ .pre-commit-config.yaml
4
+ .python-version
5
+ LICENSE
6
+ README.md
7
+ dash_qt_demo.py
8
+ dash_qt_demo2.py
9
+ dash_tooltip_demo.py
10
+ pyproject.toml
11
+ uv.lock
12
+ .github/workflows/Pytest.yml
13
+ .github/workflows/codeql.yml
14
+ Dash_tooltip.egg-info/PKG-INFO
15
+ Dash_tooltip.egg-info/SOURCES.txt
16
+ Dash_tooltip.egg-info/dependency_links.txt
17
+ Dash_tooltip.egg-info/requires.txt
18
+ Dash_tooltip.egg-info/top_level.txt
19
+ dash_tooltip/__init__.py
20
+ dash_tooltip/_version.py
21
+ dash_tooltip/config.py
22
+ dash_tooltip/custom_figure.py
23
+ dash_tooltip/utils.py
24
+ tests/__init__.py
25
+ tests/test_11_direct_figure_in_dcc_graph.py
26
+ tests/test_12_go_scatter.py
27
+ tests/test_13_go_scatter_line.py
28
+ tests/test_14_go_bar_chart.py
29
+ tests/test_16_update_template.py
30
+ tests/test_17_annotation_relayout_persistence.py
31
+ tests/test_1_tooltip_function.py
32
+ tests/test_2_tooltip_configuration.py
33
+ tests/test_3_template_formating.py
34
+ tests/test_4a_multiple_graph.py
35
+ tests/test_4b_multiple_graph.py
36
+ tests/test_6_invalid_graph_id.py
37
+ tests/test_7_tooltip_removal.py
38
+ tests/test_8__display_click_data.py
39
+ tests/test_dummy.py
@@ -0,0 +1,2 @@
1
+ dash>=2.13.0
2
+ plotly>=5.17.0
@@ -0,0 +1 @@
1
+ dash_tooltip
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 kb-
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.