From addb7a2fdf2d74e8dd4176b73fb23e3dc36f3763 Mon Sep 17 00:00:00 2001 From: emilhe Date: Wed, 24 Apr 2024 12:33:02 +0200 Subject: [PATCH] Preparing 1.0.15 release --- CHANGELOG.md | 4 ++ README.md | 2 +- dash_extensions/_imports_.py | 2 + package.json | 2 +- pyproject.toml | 2 +- src/lib/components/Loading.react.js | 93 +++++++++++++++++++++++++++++ src/lib/index.js | 4 +- 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 src/lib/components/Loading.react.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 55ee54a..0c78239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## [1.0.15] - UNRELEASED + +- Add new `Loading` component + ## [1.0.14] - 05-03-24 - Add new `validate` module, which adds an `assert_no_random_ids` that assets that Dash didn't generate any random component ids diff --git a/README.md b/README.md index 497bbdf..c219244 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The `dash-extensions` package is a collection of utility functions, syntax exten * A number of custom components, e.g. the `Websocket` component, which enables real-time communication and push notifications * The `javascript` module, which contains functionality to ease the interplay between Dash and JavaScript * The `pages` module, which extends the functionality of [Dash Pages](https://dash.plotly.com/urls) -* The `snippets/validation` modules, which contains a collection of utility functions (documentation limited to source code comments) +* The `snippets/validation` modules, which contain a collection of utility functions (documentation limited to source code comments) The `enrich` module enables a number of _transforms_ that add functionality and/or syntactic sugar to Dash. Examples include diff --git a/dash_extensions/_imports_.py b/dash_extensions/_imports_.py index ef0d000..ad5c62d 100644 --- a/dash_extensions/_imports_.py +++ b/dash_extensions/_imports_.py @@ -4,6 +4,7 @@ from .EventListener import EventListener from .EventSource import EventSource from .Keyboard import Keyboard +from .Loading import Loading from .Lottie import Lottie from .Mermaid import Mermaid from .Purify import Purify @@ -16,6 +17,7 @@ "EventListener", "EventSource", "Keyboard", + "Loading", "Lottie", "Mermaid", "Purify", diff --git a/package.json b/package.json index aad8df8..23a5354 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dash-extensions", - "version": "1.0.14", + "version": "1.0.15rc2", "description": "Extensions for Plotly Dash.", "main": "build/index.js", "scripts": { diff --git a/pyproject.toml b/pyproject.toml index 0773562..ea51d90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dash-extensions" -version = "1.0.14" +version = "1.0.15rc2" description = "Extensions for Plotly Dash." authors = ["emher "] license = "MIT" diff --git a/src/lib/components/Loading.react.js b/src/lib/components/Loading.react.js new file mode 100644 index 0000000..6c3ec15 --- /dev/null +++ b/src/lib/components/Loading.react.js @@ -0,0 +1,93 @@ +import { useEffect, useRef } from "react"; +import PropTypes from 'prop-types'; + +/** + * The Loading component makes it possible to stop event propagation during loading. + */ + +const Loading = (props) => { + const { + children, + loading_state, + preventDefault + } = props; + const container = useRef(); + + useEffect(() => { + const mounted = container && container.current; + const handlePreventDefault = (e) => { + e.preventDefault(); + } + if(mounted){ + const ref = container.current; + const loading = loading_state && loading_state.is_loading; + if(!loading){ + preventDefault.forEach(event => {ref.removeEventListener(event, handlePreventDefault, true);}) + } + else{ + preventDefault.forEach(event => {ref.addEventListener(event, handlePreventDefault, true);}) + } + } + return () => { + const mounted = container && container.current; + if(mounted){ + const ref = container.current; + preventDefault.forEach(event => {ref.removeEventListener(event, handlePreventDefault, true);}) + } + }; + }, [loading_state]); + + return ( +
+ {children} +
+ ); +}; + +Loading._dashprivate_isLoadingComponent = true; + +Loading.defaultProps = { + preventDefault: ["keydown"], +}; + +Loading.propTypes = { + /** + * The ID of this component, used to identify dash components + * in callbacks. The ID needs to be unique across all of the + * components in an app. + */ + id: PropTypes.string, + + /** + * Events for which to call preventDefault() during loading. + */ + preventDefault: PropTypes.arrayOf(PropTypes.string), + + /** + * Array that holds components to render + */ + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]), + + /** + * Object that holds the loading state object coming from dash-renderer + */ + loading_state: PropTypes.shape({ + /** + * Determines if the component is loading or not + */ + is_loading: PropTypes.bool, + /** + * Holds which property is loading + */ + prop_name: PropTypes.string, + /** + * Holds the name of the component that is loading + */ + component_name: PropTypes.string, + }), +}; + +export default Loading; diff --git a/src/lib/index.js b/src/lib/index.js index 9c1cee8..4b1febe 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -9,6 +9,7 @@ import EventListener from "./components/EventListener.react"; import EventSource from "./components/EventSource.react"; import CycleBreaker from "./components/CycleBreaker.react"; import Keyboard from "./components/Keyboard.react"; +import Loading from "./components/Loading.react"; export { Lottie, @@ -20,5 +21,6 @@ export { EventListener, EventSource, CycleBreaker, - Keyboard + Keyboard, + Loading };