Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async loading #521

Merged
merged 21 commits into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
### Changed
- `notification` will now automatically set its `action` to `hide` when closed, this avoids issues where a `callback` error would re-trigger the component. #523 by @BSd3v
- Removed `draggable` and `speed` prop from `Carousel` since these props are not supported in Embla Carousel V8. #520 by @AnnMarieW
- graphs and code highlight components now loaded async, reducing the dash_mantine_components.js file size from 2.68 MiB to 823 KiB #521 by @AnnMarieW

# 1.0.0rc2

Expand Down
57 changes: 43 additions & 14 deletions dash_mantine_components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
# noinspection PyUnresolvedReferences
from ._imports_ import *
from ._imports_ import __all__
from .theme import DEFAULT_THEME
from .figure_templates import add_figure_templates
from .theme import DEFAULT_THEME

if not hasattr(_dash, "__plotly_dash") and not hasattr(_dash, "development"):
print(
Expand All @@ -35,34 +35,63 @@

_this_module = _sys.modules[__name__]

# Add async components here.
async_resources = [
"AreaChart",
"BarChart",
"LineChart",
"BubbleChart",
"DonutChart",
"PieChart",
"RadarChart",
"ScatterChart",
"CompositeChart",
"Sparkline",
"CodeHighlight",
"CodeHighlightTabs",
"InlineCodeHighlight",
]
async_chunks = [f"async-{async_resource}" for async_resource in async_resources]

# Add shared chunks here.
shared_chunks = [
f"{__name__}-shared",
f"{__name__}-charts-shared",
]

# Collect all chunks (main, async, shared).
chunks = [__name__] + async_chunks + shared_chunks

# Add all chunks to the js_dist list.
_js_dist = []

_js_dist.extend(
[
{
"relative_package_path": "dash_mantine_components.js",
"external_url": "https://unpkg.com/{0}@{2}/{1}/{1}.js".format(
package_name, __name__, __version__
),
"relative_package_path": f"{chunk}.js",
"external_url": f"https://unpkg.com/{package_name}@{__version__}/{__name__}/{chunk}.js",
"namespace": package_name,
},
"async": chunk != __name__, # don't make the main bundle async
}
for chunk in chunks
]
)
_js_dist.extend(
[
{
"relative_package_path": "dash_mantine_components.js.map",
"external_url": "https://unpkg.com/{0}@{2}/{1}/{1}.js.map".format(
package_name, __name__, __version__
),
"relative_package_path": f"{chunk}.js.map",
"external_url": f"https://unpkg.com/{package_name}@{__version__}/{__name__}/{chunk}.js.map",
"namespace": package_name,
"dynamic": True,
},
}
for chunk in chunks
]
)

# Similarly, collect CSS.
_css_dist = []


for _component in __all__:
setattr(locals()[_component], "_js_dist", _js_dist)
setattr(locals()[_component], "_css_dist", _css_dist)


__all__ += [DEFAULT_THEME, styles, add_figure_templates]
2 changes: 1 addition & 1 deletion dash_mantine_components/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
CAROUSEL = "https://unpkg.com/@mantine/[email protected]/styles.css"
NOTIFICATIONS = "https://unpkg.com/@mantine/[email protected]/styles.css"
NPROGRESS = "https://unpkg.com/@mantine/[email protected]/styles.css"
ALL = [DATES, CODE_HIGHLIGHT, CHARTS, CAROUSEL, NOTIFICATIONS, NPROGRESS]
ALL = [DATES, CODE_HIGHLIGHT, CHARTS, CAROUSEL, NOTIFICATIONS, NPROGRESS]
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"homepage": "https://github.com/snehilvj/dash-mantine-components",
"scripts": {
"build:js::dev": "webpack --mode development",
"build:js": "webpack",
"build:js": "webpack --mode production",
"build:backends": "dash-generate-components ./src/ts/components dash_mantine_components -p package-info.json --r-prefix '' --jl-prefix '' --ignore \\.test\\.",
"build": "npm run build:js && npm run build:backends",
"watch": "npm run build:js::dev -- --watch",
Expand All @@ -23,6 +23,7 @@
"@braintree/sanitize-url": "^7.1.0",
"@types/ramda": "^0.30.1",
"@types/react": "^18.2.55",
"@plotly/webpack-dash-dynamic-import": "^1.3.0",
"css-loader": "^6.10.0",
"dash-extensions-js": "^0.0.8",
"npm-run-all": "^2.1.0",
Expand Down
126 changes: 10 additions & 116 deletions src/ts/components/charts/AreaChart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AreaChart as MantineAreaChart } from "@mantine/charts";
import React, { Suspense } from 'react';
import {
AreaChartCurveType,
AreaChartSeries,
Expand All @@ -9,11 +9,12 @@ import { BoxProps } from "props/box";
import { GridChartBaseProps } from "props/charts";
import { DashBaseProps } from "props/dash";
import { StylesApiProps } from "props/styles";
import React, { useState, useRef } from "react";
import { getClickData, isEventValid } from "../../utils/charts";
import { getLoadingState } from "../../utils/dash3";

interface Props
// eslint-disable-next-line no-inline-comments
const LazyAreaChart = React.lazy(() => import(/* webpackChunkName: "AreaChart" */ './fragments/AreaChart'));


export interface Props
extends BoxProps,
GridChartBaseProps,
StylesApiProps,
Expand Down Expand Up @@ -65,118 +66,11 @@ interface Props
}

/** AreaChart */
const AreaChart = ({
setProps,
loading_state,
clickData,
hoverData,
clickSeriesName,
hoverSeriesName,
series,
highlightHover = false,
areaChartProps,
activeDotProps,
areaProps,
...others }: Props) => {

const [highlightedArea, setHighlightedArea] = useState(null);
const shouldHighlight = highlightHover && highlightedArea !== null;

const seriesName = useRef(null);

const onClick = (ev) => {
if (isEventValid(ev)) {
setProps({
clickSeriesName: seriesName.current,
clickData: getClickData(ev)
});
}
seriesName.current = null;
};

const onMouseOver = (ev) => {
if (isEventValid(ev)) {
setProps({
hoverSeriesName: seriesName.current,
hoverData: getClickData(ev)
});
}
seriesName.current = null;

};

const handleSeriesClick= (ev) => {
if (isEventValid(ev)) {
seriesName.current = ev["name"];
}
};

const handleSeriesHover = (ev) => {
if (isEventValid(ev)) {
const hoveredSeriesName = ev["name"];

seriesName.current = hoveredSeriesName;
setHighlightedArea(hoveredSeriesName);
}
};

const handleDotClick = (ev, payload) => {
if (isEventValid(ev)) {
seriesName.current = payload["dataKey"];
}
}

const handleDotHover = (ev, payload) => {
if (isEventValid(ev)) {
const hoveredSeriesName = payload["dataKey"];
seriesName.current = hoveredSeriesName;
setHighlightedArea(hoveredSeriesName);
}
};


const handleHoverEnd = () => {
setHighlightedArea(null); // Reset highlighted area
};

const areaPropsFunction = (item) => {
const dimmed = shouldHighlight && highlightedArea !== item.name;

const returnProps : any = {
...areaProps,
onClick: handleSeriesClick,
onMouseOver: handleSeriesHover,
onMouseOut: handleHoverEnd,
};

/**if not dimmed, default behavior of Opacity will be triggered, including Hover over chart legend (BarChart.mjs)
fillOpacity: dimmed ? 0.1 : fillOpacity,
strokeOpacity: dimmed ? 0.2 : 0,
*/
if (dimmed) {
returnProps.fillOpacity = 0.1;
returnProps.strokeOpacity = 0.2;
}

return returnProps;
};

const newProps = { ...areaChartProps, onClick, onMouseOver };

const AreaChart = (props: Props) => {
return (
<MantineAreaChart
data-dash-is-loading={getLoadingState(loading_state) || undefined}
areaChartProps={newProps}
series={series}
activeDotProps={{
...activeDotProps,
onClick: handleDotClick,
onMouseOver: handleDotHover,
onMouseOut: handleHoverEnd,
}}
areaProps={areaPropsFunction}
{...others}
/>
<Suspense fallback={null}>
<LazyAreaChart {...props} />
</Suspense>
);
}

Expand Down
Loading