Skip to content

Commit 551d149

Browse files
authored
Merge pull request #3275 from plotly/master-3.0.3
Master 3.0.3
2 parents 2525a3d + 572e3a6 commit 551d149

File tree

207 files changed

+3976
-1185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

207 files changed

+3976
-1185
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
All notable changes to `dash` will be documented in this file.
33
This project adheres to [Semantic Versioning](https://semver.org/).
44

5+
## [3.0.3] - 2025-04-14
6+
7+
## Fixed
8+
- [#3264](https://github.com/plotly/dash/pull/3264) Fixed an issue where moving components inside of children would not update the `setProps` path, leading to hashes being incorrect
9+
- [#3265](https://github.com/plotly/dash/pull/3265) Fixed issue where the resize of graphs was cancelling others
10+
- [#3273](https://github.com/plotly/dash/pull/3273) Fix hooks entry point, renamed from invalid hyphen `dash-hooks` to underscored `dash_hooks`. Fix [#3272](https://github.com/plotly/dash/issues/3272)
11+
- [#3271](https://github.com/plotly/dash/pull/3271) fix issue with tooltip styling. Fix [#3269](https://github.com/plotly/dash/issues/3269)
12+
13+
## Added
14+
- [#3268](https://github.com/plotly/dash/pull/3268) Added the ability for component devs to subscribe to descendent updates by setting `dashChildrenUpdate = true` on the component, eg: `Tabs.dashChildrenUpdate = true`
15+
516
## [3.0.2] - 2025-04-01
617

718
## Changed
@@ -17,6 +28,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
1728
## Added
1829
- [#3248](https://github.com/plotly/dash/pull/3248) added new `dashRenderType` to determine why the component layout was changed (`internal`, `callback`, `parent`, `clientsideApi`):
1930
- this can be utilized to keep from rendering components by the component having `dashRenderType` defined as a prop, and the `dashRenderType = true` must be set on the component, eg (`Div.dashRenderType = true`)
31+
- [#3241](https://github.com/plotly/dash/pull/3241) Added a collapse / expand button to Dash Dev Tools.
2032

2133
## [3.0.1] - 2025-03-24
2234

components/dash-core-components/dash_core_components_base/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
send_string,
1414
)
1515

16-
__all__ = _components + [
16+
__all__ = _components + [ # type: ignore[reportUnsupportedDunderAll]
1717
"send_bytes",
1818
"send_data_frame",
1919
"send_file",

components/dash-core-components/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/dash-core-components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dash-core-components",
3-
"version": "3.0.4",
3+
"version": "3.0.5",
44
"description": "Core component suite for Dash",
55
"repository": {
66
"type": "git",

components/dash-core-components/src/components/Tabs.react.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,6 @@ const EnhancedTab = ({
121121
);
122122
};
123123

124-
EnhancedTab.defaultProps = {
125-
loading_state: {
126-
is_loading: false,
127-
component_name: '',
128-
prop_name: '',
129-
},
130-
};
131-
132124
/**
133125
* A Dash component that lets you render pages with tabs - the Tabs component's children
134126
* can be dcc.Tab components, which can hold a label that will be displayed as a tab, and can in turn hold
@@ -439,3 +431,5 @@ Tabs.propTypes = {
439431
*/
440432
persistence_type: PropTypes.oneOf(['local', 'session', 'memory']),
441433
};
434+
435+
Tabs.dashChildrenUpdate = true;

components/dash-core-components/src/components/Tooltip.react.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33

44
import _JSXStyle from 'styled-jsx/style'; // eslint-disable-line no-unused-vars
5-
import LoadingElement from '../utils/LoadingElement';
65

76
/**
87
* A tooltip with an absolute position.
@@ -27,9 +26,9 @@ const Tooltip = ({
2726
return (
2827
<>
2928
<div className="dcc-tooltip-bounding-box">
30-
<LoadingElement
31-
elementType="span"
29+
<div
3230
className={`hover hover-${direction}`}
31+
data-dash-is-loading={is_loading}
3332
>
3433
<span
3534
id={id}
@@ -42,7 +41,7 @@ const Tooltip = ({
4241
props.children
4342
)}
4443
</span>
45-
</LoadingElement>
44+
</div>
4645
</div>
4746
<style jsx>{`
4847
.dcc-tooltip-bounding-box {

components/dash-core-components/src/utils/ResizeDetector.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import PropTypes from 'prop-types';
44
// Debounce 50 ms
55
const DELAY = 50;
66

7-
let resizeTimeout;
8-
97
const ResizeDetector = props => {
108
const {onResize, children, targets} = props;
119
const ref = createRef();
10+
let resizeTimeout;
1211

1312
const debouncedResizeHandler = useCallback(() => {
1413
if (resizeTimeout) {

components/dash-core-components/tests/integration/graph/test_graph_responsive.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from dash import Dash, Input, Output, State, dcc, html
4+
import plotly.graph_objects as go
45

56
from dash.exceptions import PreventUpdate
67
from dash.testing import wait
@@ -134,3 +135,77 @@ def resize(n_clicks, style):
134135
)
135136

136137
assert dash_dcc.get_logs() == []
138+
139+
140+
def test_grrs002_graph(dash_dcc):
141+
app = Dash(__name__)
142+
143+
app.layout = html.Div(
144+
[
145+
html.Button("Generate Figures", id="generate-btn", n_clicks=0),
146+
html.Button("Get Bounding Box", id="bounding-btn"),
147+
html.Div(
148+
id="graph-container",
149+
children=[
150+
html.Div(id="bounding-output"),
151+
dcc.Graph(
152+
id="prec-climate-daily",
153+
style={"height": "45vh"},
154+
config={"responsive": True},
155+
),
156+
dcc.Graph(
157+
id="temp-climate-daily",
158+
style={"height": "45vh"},
159+
config={"responsive": True},
160+
),
161+
],
162+
style={"display": "none"},
163+
),
164+
]
165+
)
166+
167+
app.clientside_callback(
168+
"""() => {
169+
pcd_container = document.querySelector("#prec-climate-daily")
170+
pcd_container_bbox = pcd_container.getBoundingClientRect()
171+
pcd_graph = pcd_container.querySelector('.main-svg')
172+
pcd_graph_bbox = pcd_graph.getBoundingClientRect()
173+
tcd_container = document.querySelector("#temp-climate-daily")
174+
tcd_container_bbox = tcd_container.getBoundingClientRect()
175+
tcd_graph = tcd_container.querySelector('.main-svg')
176+
tcd_graph_bbox = tcd_graph.getBoundingClientRect()
177+
return JSON.stringify(
178+
pcd_container_bbox.height == pcd_graph_bbox.height &&
179+
pcd_container_bbox.width == pcd_graph_bbox.width &&
180+
tcd_container_bbox.height == tcd_graph_bbox.height &&
181+
tcd_container_bbox.width == tcd_graph_bbox.width
182+
)
183+
}""",
184+
Output("bounding-output", "children"),
185+
Input("bounding-btn", "n_clicks"),
186+
prevent_initial_call=True,
187+
)
188+
189+
@app.callback(
190+
[
191+
Output("prec-climate-daily", "figure"),
192+
Output("temp-climate-daily", "figure"),
193+
Output("graph-container", "style"),
194+
Output("bounding-output", "children", allow_duplicate=True),
195+
],
196+
[Input("generate-btn", "n_clicks")],
197+
prevent_initial_call=True,
198+
)
199+
def update_figures(n_clicks):
200+
fig_acc = go.Figure(data=[go.Scatter(x=[0, 1, 2], y=[0, 1, 0], mode="lines")])
201+
fig_daily = go.Figure(data=[go.Scatter(x=[0, 1, 2], y=[1, 0, 1], mode="lines")])
202+
return fig_acc, fig_daily, {"display": "block"}, "loaded"
203+
204+
dash_dcc.start_server(app)
205+
dash_dcc.wait_for_text_to_equal("#generate-btn", "Generate Figures")
206+
dash_dcc.find_element("#generate-btn").click()
207+
dash_dcc.wait_for_text_to_equal("#bounding-output", "loaded")
208+
dash_dcc.wait_for_element(".dash-graph .js-plotly-plot.dash-graph--pending")
209+
dash_dcc.wait_for_element(".dash-graph .js-plotly-plot:not(.dash-graph--pending)")
210+
dash_dcc.find_element("#bounding-btn").click()
211+
dash_dcc.wait_for_text_to_equal("#bounding-output", "true")

components/dash-table/dash_table_base/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# type: ignore
2+
13
import os as _os
24
import sys as _sys
35
import json

components/dash-table/src/dash-table/dash/DataTable.js

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -472,25 +472,14 @@ export const propTypes = {
472472
* View the documentation examples to learn more.
473473
*
474474
*/
475-
fixed_columns: PropTypes.oneOfType([
476-
PropTypes.exact({
477-
/**
478-
* Example `{'headers':False, 'data':0}` No columns are fixed (the default)
479-
*/
480-
481-
data: PropTypes.oneOf([0]),
482-
headers: PropTypes.oneOf([false])
483-
}),
484-
485-
PropTypes.exact({
486-
/**
487-
* Example `{'headers':True, 'data':1}` one column is fixed.
488-
*/
475+
fixed_columns: PropTypes.exact({
476+
/**
477+
* Example `{'headers':False, 'data':0}` No columns are fixed (the default)
478+
*/
489479

490-
data: PropTypes.number,
491-
headers: PropTypes.oneOf([true]).isRequired
492-
})
493-
]),
480+
data: PropTypes.number,
481+
headers: PropTypes.bool
482+
}),
494483

495484
/**
496485
* `fixed_rows` will "fix" the set of rows so that
@@ -505,24 +494,14 @@ export const propTypes = {
505494
* way that your columns are rendered or sized.
506495
* View the documentation examples to learn more.
507496
*/
508-
fixed_rows: PropTypes.oneOfType([
509-
PropTypes.exact({
510-
/**
511-
* Example `{'headers':False, 'data':0}` No rows are fixed (the default)
512-
*/
513-
514-
data: PropTypes.oneOf([0]),
515-
headers: PropTypes.oneOf([false])
516-
}),
517-
PropTypes.exact({
518-
/**
519-
* Example `{'headers':True, 'data':1}` one row is fixed.
520-
*/
497+
fixed_rows: PropTypes.exact({
498+
/**
499+
* Example `{'headers':False, 'data':0}` No rows are fixed (the default)
500+
*/
521501

522-
data: PropTypes.number,
523-
headers: PropTypes.oneOf([true]).isRequired
524-
})
525-
]),
502+
data: PropTypes.number,
503+
headers: PropTypes.bool
504+
}),
526505

527506
/**
528507
* If `single`, then the user can select a single column or group

dash/_callback.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def callback(
7777
cache_ignore_triggered=True,
7878
on_error: Optional[Callable[[Exception], Any]] = None,
7979
**_kwargs,
80-
):
80+
) -> Callable[..., Any]:
8181
"""
8282
Normally used as a decorator, `@dash.callback` provides a server-side
8383
callback relating the values of one or more `Output` items to one or
@@ -124,6 +124,7 @@ def callback(
124124
while a callback is running, the callback is canceled.
125125
Note that the value of the property is not significant, any change in
126126
value will result in the cancellation of the running job (if any).
127+
This parameter only applies to background callbacks (`background=True`).
127128
:param progress:
128129
An `Output` dependency grouping that references properties of
129130
components in the app's layout. When provided, the decorated function
@@ -132,21 +133,25 @@ def callback(
132133
function should call in order to provide updates to the app on its
133134
current progress. This function accepts a single argument, which
134135
correspond to the grouping of properties specified in the provided
135-
`Output` dependency grouping
136+
`Output` dependency grouping. This parameter only applies to background
137+
callbacks (`background=True`).
136138
:param progress_default:
137139
A grouping of values that should be assigned to the components
138140
specified by the `progress` argument when the callback is not in
139141
progress. If `progress_default` is not provided, all the dependency
140142
properties specified in `progress` will be set to `None` when the
141-
callback is not running.
143+
callback is not running. This parameter only applies to background
144+
callbacks (`background=True`).
142145
:param cache_args_to_ignore:
143146
Arguments to ignore when caching is enabled. If callback is configured
144147
with keyword arguments (Input/State provided in a dict),
145148
this should be a list of argument names as strings. Otherwise,
146149
this should be a list of argument indices as integers.
150+
This parameter only applies to background callbacks (`background=True`).
147151
:param cache_ignore_triggered:
148152
Whether to ignore which inputs triggered the callback when creating
149-
the cache.
153+
the cache. This parameter only applies to background callbacks
154+
(`background=True`).
150155
:param interval:
151156
Time to wait between the background callback update requests.
152157
:param on_error:
@@ -360,7 +365,9 @@ def register_callback(
360365
# pylint: disable=too-many-locals
361366
def wrap_func(func):
362367

363-
if background is not None:
368+
if background is None:
369+
background_key = None
370+
else:
364371
background_key = BaseBackgroundCallbackManager.register_func(
365372
func,
366373
background.get("progress") is not None,
@@ -515,7 +522,7 @@ def add_context(*args, **kwargs):
515522
return to_json(response)
516523
else:
517524
try:
518-
output_value = _invoke_callback(func, *func_args, **func_kwargs)
525+
output_value = _invoke_callback(func, *func_args, **func_kwargs) # type: ignore[reportArgumentType]
519526
except PreventUpdate as err:
520527
raise err
521528
except Exception as err: # pylint: disable=broad-exception-caught
@@ -555,7 +562,7 @@ def add_context(*args, **kwargs):
555562
if NoUpdate.is_no_update(val):
556563
continue
557564
for vali, speci in (
558-
zip(val, spec) if isinstance(spec, list) else [[val, spec]]
565+
zip(val, spec) if isinstance(spec, list) else [[val, spec]] # type: ignore[reportArgumentType]]
559566
):
560567
if not NoUpdate.is_no_update(vali):
561568
has_update = True
@@ -590,6 +597,7 @@ def add_context(*args, **kwargs):
590597
dist = app.get_dist(diff_packages)
591598
response["dist"] = dist
592599

600+
jsonResponse = None
593601
try:
594602
jsonResponse = to_json(response)
595603
except TypeError:

dash/_callback_context.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,15 @@ def response(self):
207207

208208
@staticmethod
209209
@has_context
210-
def record_timing(name, duration=None, description=None):
210+
def record_timing(name, duration, description=None):
211211
"""Records timing information for a server resource.
212212
213213
:param name: The name of the resource.
214214
:type name: string
215215
216216
:param duration: The time in seconds to report. Internally, this
217217
is rounded to the nearest millisecond.
218-
:type duration: float or None
218+
:type duration: float
219219
220220
:param description: A description of the resource.
221221
:type description: string or None

dash/_dash_renderer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22

3-
__version__ = "2.0.6"
3+
__version__ = "2.0.7"
44

55
_available_react_versions = {"18.3.1", "18.2.0", "16.14.0"}
66
_available_reactdom_versions = {"18.3.1", "18.2.0", "16.14.0"}
@@ -64,7 +64,7 @@ def _set_react_version(v_react, v_reactdom=None):
6464
{
6565
"relative_package_path": "dash-renderer/build/dash_renderer.min.js",
6666
"dev_package_path": "dash-renderer/build/dash_renderer.dev.js",
67-
"external_url": "https://unpkg.com/[email protected].6"
67+
"external_url": "https://unpkg.com/[email protected].7"
6868
"/build/dash_renderer.min.js",
6969
"namespace": "dash",
7070
},

0 commit comments

Comments
 (0)