dash-startup-loading-plugin 0.1.0__tar.gz → 0.3.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 (19) hide show
  1. {dash_startup_loading_plugin-0.1.0/src/dash_startup_loading_plugin.egg-info → dash_startup_loading_plugin-0.3.0}/PKG-INFO +190 -46
  2. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/README.md +185 -43
  3. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/pyproject.toml +6 -3
  4. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin/__init__.py +6 -2
  5. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin/plugin.py +98 -21
  6. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin/resources/startup-loading.css +6 -8
  7. dash_startup_loading_plugin-0.3.0/src/dash_startup_loading_plugin/resources/startup-theme.js +102 -0
  8. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0/src/dash_startup_loading_plugin.egg-info}/PKG-INFO +190 -46
  9. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin.egg-info/SOURCES.txt +1 -0
  10. dash_startup_loading_plugin-0.3.0/src/dash_startup_loading_plugin.egg-info/requires.txt +7 -0
  11. dash_startup_loading_plugin-0.3.0/tests/test_plugin.py +196 -0
  12. dash_startup_loading_plugin-0.1.0/src/dash_startup_loading_plugin.egg-info/requires.txt +0 -4
  13. dash_startup_loading_plugin-0.1.0/tests/test_plugin.py +0 -104
  14. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/LICENSE +0 -0
  15. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/setup.cfg +0 -0
  16. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin/resources/startup-loading.js +0 -0
  17. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin.egg-info/dependency_links.txt +0 -0
  18. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin.egg-info/entry_points.txt +0 -0
  19. {dash_startup_loading_plugin-0.1.0 → dash_startup_loading_plugin-0.3.0}/src/dash_startup_loading_plugin.egg-info/top_level.txt +0 -0
@@ -1,17 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dash-startup-loading-plugin
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: A configurable full-screen startup loading overlay for Dash apps, packaged as a Dash Hooks plugin.
5
5
  Author-email: Ethan Zhang <ethan.zhang2016@gmail.com>
6
6
  License-Expression: MIT
7
- Keywords: dash,plotly,loading,plugin,hooks
7
+ Keywords: dash,plotly,loading,plugin
8
8
  Classifier: Framework :: Dash
9
9
  Requires-Python: >=3.9
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
- Requires-Dist: dash>=3.0.3
12
+ Requires-Dist: dash==4.4.1
13
13
  Provides-Extra: test
14
14
  Requires-Dist: pytest>=8; extra == "test"
15
+ Provides-Extra: mantine
16
+ Requires-Dist: dash-mantine-components>=2.6.0; extra == "mantine"
15
17
  Dynamic: license-file
16
18
 
17
19
  # dash-startup-loading-plugin
@@ -20,10 +22,10 @@ Dynamic: license-file
20
22
  that displays a full-screen loading overlay while a Dash application performs
21
23
  its initial browser-side startup.
22
24
 
23
- The overlay is injected into the final HTML document with `hooks.index`, so it
24
- is visible before Dash and React mount the application layout. The packaged CSS
25
- and JavaScript are registered with `hooks.stylesheet` and `hooks.script`; an app
26
- does not need to copy assets or replace Dash's `index_string`.
25
+ The overlay, CSS, and JavaScript are injected into the final HTML document with
26
+ `hooks.index`, so they are available before Dash and React mount the application
27
+ layout without additional startup resource requests. An app does not need to
28
+ copy assets or replace Dash's `index_string`.
27
29
 
28
30
  ## Features
29
31
 
@@ -32,8 +34,10 @@ does not need to copy assets or replace Dash's `index_string`.
32
34
  - Waits for real rendered content and optional app-specific readiness selectors.
33
35
  - Can wait for lazy-loading placeholders to disappear.
34
36
  - Includes a timeout fallback, minimum display time, and fade-out transition.
35
- - Supports light and dark themes, reduced-motion preferences, custom colors,
36
- custom spinner geometry, and trusted custom loader markup.
37
+ - Inlines its small startup CSS and JavaScript, avoiding two additional requests.
38
+ - Resolves light and dark themes before first paint from Dash component
39
+ persistence, Tailwind root classes, Mantine color-scheme state, or the
40
+ operating-system preference.
37
41
  - Exposes a small browser API and emits a completion event.
38
42
  - Requires no changes to the app layout or callbacks.
39
43
 
@@ -49,7 +53,7 @@ discovery, resource hooks, and the index hook described in the official
49
53
  ## Installation
50
54
 
51
55
  ```bash
52
- pip install dash-startup-loading-plugin
56
+ pip install "dash-startup-loading-plugin>=0.3.0"
53
57
  ```
54
58
 
55
59
  The package declares the following entry point:
@@ -64,6 +68,27 @@ package therefore enables the default startup overlay for Dash applications in
64
68
  that Python environment; an explicit import is only needed when changing its
65
69
  configuration or using its Python API.
66
70
 
71
+ ## What's new in 0.3.0
72
+
73
+ - Adds `configure_antd()` with matching `#ffffff` and `#121212` loading
74
+ backgrounds plus explicit light/dark overrides.
75
+ - Adds `configure_mantine()` with theme defaults sourced from Dash Mantine
76
+ Components and its pre-render color-scheme hook.
77
+ - Updates the Dash Ant Design example for the structured
78
+ `ConfigProvider.theme.algorithm` API.
79
+ - Adds a Dash Mantine Components example with persisted theme switching.
80
+
81
+ ## What's new in 0.2.0
82
+
83
+ - Resolves the loading background before first paint from a persisted
84
+ `dash_antd_components.ConfigProvider.theme`.
85
+ - Supports Tailwind's `html.dark` and `html.light` classes.
86
+ - Supports Dash Mantine Components' `data-mantine-color-scheme` attribute and
87
+ `mantine-color-scheme-value` localStorage entry.
88
+ - Adds `theme_mode` and `dash_theme_component_id` configuration.
89
+ - Keeps the startup CSS and JavaScript inline, so theme detection does not add
90
+ network requests before Dash mounts.
91
+
67
92
  ## Quick start
68
93
 
69
94
  The defaults work without any plugin-specific code:
@@ -91,25 +116,33 @@ from dash import Dash, html
91
116
  from dash_startup_loading_plugin import configure
92
117
 
93
118
  configure(
94
- required_selectors=["#page-header", "#sidebar-menu"],
119
+ required_selectors=["#usage-header", "#usage-sidebar-menu"],
95
120
  pending_selector="[data-dac-async-placeholder]",
96
121
  timeout_ms=6000,
97
- minimum_display_ms=200,
98
122
  fade_duration_ms=160,
99
- color="#1677ff",
100
- dark_color="#4096ff",
101
123
  )
102
124
 
103
125
  app = Dash(__name__)
104
126
  app.layout = html.Div(
105
127
  [
106
- html.Header("Dashboard", id="page-header"),
107
- html.Nav("Navigation", id="sidebar-menu"),
128
+ html.Header("Dashboard", id="usage-header"),
129
+ html.Nav("Navigation", id="usage-sidebar-menu"),
108
130
  ]
109
131
  )
110
132
  ```
111
133
 
112
- See [`examples/basic.py`](examples/basic.py) for a runnable example.
134
+ Runnable examples:
135
+
136
+ - [`examples/basic.py`](examples/basic.py): Dash Ant Design theme persistence.
137
+ - [`examples/mantine_theme.py`](examples/mantine_theme.py):
138
+ Dash Mantine Components with a persisted light/dark theme switch.
139
+
140
+ Run the Mantine example with:
141
+
142
+ ```bash
143
+ pip install -e ".[mantine]"
144
+ python examples/mantine_theme.py
145
+ ```
113
146
 
114
147
  ## Readiness behavior
115
148
 
@@ -152,14 +185,133 @@ immutable `StartupLoadingConfig` instance.
152
185
  | `dark_background` | `"#0f0f0f"` | Dark-theme background color. |
153
186
  | `color` | `"#1677ff"` | Light-theme spinner/current color. |
154
187
  | `dark_color` | `"#4096ff"` | Dark-theme spinner/current color. |
188
+ | `theme_mode` | `"auto"` | Startup theme policy: `"auto"`, `"light"`, or `"dark"`. Auto follows persisted or active app state, then the operating-system preference. |
189
+ | `dash_theme_component_id` | `None` | Preferred Dash component ID when reading a persisted `theme` prop. When omitted, the first compatible persisted theme is used. |
155
190
  | `spinner_size_px` | `28` | Default spinner width and height in pixels. |
156
191
  | `spinner_stroke_px` | `3` | Default spinner stroke width in pixels. |
157
192
  | `hide_default_loading` | `True` | Hide Dash's built-in initial `._dash-loading` indicator while the overlay is present. |
158
193
  | `custom_loader_html` | `None` | Trusted HTML that replaces the default spinner. |
159
194
 
160
- The default stylesheet recognizes `html.dark` and `html.light`. When neither
161
- class forces a theme, it follows `prefers-color-scheme`. It also adjusts its
162
- animation when the user enables `prefers-reduced-motion`.
195
+ With `theme_mode="auto"`, the inline head bootstrap resolves the startup theme
196
+ in this order:
197
+
198
+ 1. The persisted Dash `theme` for `dash_theme_component_id`, when configured.
199
+ 2. An existing `html.dark` or `html.light` class, including Tailwind's manual
200
+ dark-mode convention.
201
+ 3. `data-theme`, `data-color-scheme`, or `data-mantine-color-scheme` on
202
+ `<html>`.
203
+ 4. Other Dash local persistence entries for a component's `theme` prop. Set
204
+ `dash_theme_component_id` when an app contains more than one persisted
205
+ theme-capable component.
206
+ 5. Dash Mantine Components' `mantine-color-scheme-value` localStorage entry,
207
+ followed by the common `theme`, `color-theme`, and `color-scheme` keys.
208
+ 6. `prefers-color-scheme`.
209
+
210
+ The result is written to `data-dash-startup-loading-theme` before the body is
211
+ parsed. This isolates the overlay styling without changing classes or data
212
+ attributes owned by Tailwind, Dash Mantine Components, or the application.
213
+ The stylesheet also adjusts its animation for `prefers-reduced-motion`.
214
+
215
+ ### Dash Mantine Components
216
+
217
+ Dash Mantine Components 2.6 and later includes `ColorSchemeToggle`, which
218
+ switches the active color scheme without a callback and persists it in
219
+ `mantine-color-scheme-value`. The startup plugin reads that value before Dash
220
+ and React mount. To make the loading transition seamless, use Mantine's current
221
+ default dark body color for the overlay:
222
+
223
+ ```python
224
+ import dash_mantine_components as dmc
225
+ from dash_startup_loading_plugin import configure_mantine
226
+
227
+ configure_mantine()
228
+
229
+ app.layout = dmc.MantineProvider(
230
+ [
231
+ dmc.ColorSchemeToggle(
232
+ lightIcon=dmc.Text("☀"),
233
+ darkIcon=dmc.Text("☾"),
234
+ ),
235
+ dmc.Text("Application content", id="app-ready"),
236
+ ],
237
+ defaultColorScheme="auto",
238
+ )
239
+ ```
240
+
241
+ See
242
+ [`examples/mantine_theme.py`](examples/mantine_theme.py)
243
+ for the complete runnable example.
244
+
245
+ `configure_mantine()` keeps DMC optional. When used, it registers DMC's
246
+ pre-render color-scheme hook, disables the Dash Ant Design placeholder check,
247
+ and derives the light and dark loading backgrounds from DMC's active default
248
+ theme. Any explicit configuration still takes precedence:
249
+
250
+ ```python
251
+ configure_mantine(dark_background="#202020")
252
+ ```
253
+
254
+ ### Dash Ant Design persistence
255
+
256
+ Current `dash_antd_components.ConfigProvider.theme` accepts a structured theme
257
+ configuration whose `algorithm` is `"default"`, `"dark"`, `"compact"`, or an
258
+ array of those values. Persist a user-facing system/light/dark selector, resolve
259
+ the system preference in a clientside callback, and store the semantic choice
260
+ in the small conventional `localStorage["theme"]` value that the startup plugin
261
+ reads before Dash mounts:
262
+
263
+ ```python
264
+ import dash_antd_components as dac
265
+ from dash import Input, Output, clientside_callback
266
+ from dash_startup_loading_plugin import configure_antd
267
+
268
+ configure_antd()
269
+
270
+ provider = dac.ConfigProvider(
271
+ [
272
+ app_content,
273
+ dac.Segmented(
274
+ id="theme-mode",
275
+ options=["system", "light", "dark"],
276
+ value="system",
277
+ persistence=True,
278
+ persisted_props=["value"],
279
+ persistence_type="local",
280
+ ),
281
+ ],
282
+ id="theme-provider",
283
+ theme={"algorithm": "default"},
284
+ )
285
+
286
+ clientside_callback(
287
+ """function(mode) {
288
+ localStorage.setItem("theme", JSON.stringify(mode));
289
+ const dark = mode === "dark" || (
290
+ mode === "system"
291
+ && window.matchMedia("(prefers-color-scheme: dark)").matches
292
+ );
293
+ return {algorithm: dark ? "dark" : "default"};
294
+ }""",
295
+ Output("theme-provider", "theme"),
296
+ Input("theme-mode", "value"),
297
+ )
298
+ ```
299
+
300
+ The selector owns the semantic `"system"` state; `ConfigProvider` receives only
301
+ the algorithms allowed by its current API. `configure_antd()` uses `#ffffff`
302
+ and `#121212`, matching the component library's default light and dark
303
+ backgrounds. If the application customizes either background, pass the same
304
+ values explicitly:
305
+
306
+ ```python
307
+ configure_antd(
308
+ background="#f5f5f5",
309
+ dark_background="#202020",
310
+ )
311
+ ```
312
+
313
+ See
314
+ [`examples/basic.py`](examples/basic.py) for the complete switcher.
163
315
 
164
316
  ### Custom loader markup
165
317
 
@@ -186,12 +338,18 @@ configuration. Never populate it with user input.
186
338
  from dash_startup_loading_plugin import (
187
339
  StartupLoadingConfig,
188
340
  configure,
341
+ configure_antd,
342
+ configure_mantine,
189
343
  get_config,
190
344
  reset_config,
191
345
  )
192
346
  ```
193
347
 
194
348
  - `configure(**changes)` validates and applies a partial configuration update.
349
+ - `configure_antd(**changes)` matches the loading backgrounds to Dash Ant
350
+ Design's light and dark themes and accepts explicit overrides.
351
+ - `configure_mantine(**changes)` applies DMC theme defaults and registers DMC's
352
+ pre-render color-scheme hook.
195
353
  - `get_config()` returns the current immutable configuration.
196
354
  - `reset_config()` restores all defaults. It is primarily useful in tests.
197
355
  - `StartupLoadingConfig` is the frozen dataclass containing all options.
@@ -241,11 +399,18 @@ configure(
241
399
  )
242
400
  ```
243
401
 
244
- The plugin preserves Dash's normal index template, injects the overlay directly
245
- after the opening `<body>` tag, and registers its versioned package assets via
246
- Dash Hooks. The index hook uses priority `100`, so it runs before lower-priority
247
- index hooks. If multiple hooks share the same priority, Dash does not guarantee
248
- their relative order.
402
+ The plugin preserves Dash's normal index template, injects its stylesheet before
403
+ `</head>`, and inserts the overlay followed by its startup script directly after
404
+ the opening `<body>` tag. The source CSS and JavaScript remain package resources
405
+ for maintainability, but the browser receives them inline and makes no separate
406
+ request for either file. The index hook uses priority `100`, so it runs before
407
+ lower-priority index hooks. If multiple hooks share the same priority, Dash does
408
+ not guarantee their relative order.
409
+
410
+ Because the resources are inline, applications with a strict Content Security
411
+ Policy must permit the injected style and script, or add nonce support in a
412
+ customized deployment. The previous external-resource form is more suitable
413
+ when a policy forbids all inline code.
249
414
 
250
415
  ## Scope and process model
251
416
 
@@ -282,27 +447,6 @@ This is expected with automatic `dash_hooks` discovery. Use a dedicated virtual
282
447
  environment, uninstall the package where it is not wanted, or call
283
448
  `configure(enabled=False)` before constructing those Dash apps.
284
449
 
285
- ## Development
286
-
287
- Clone the repository, then install the project and test dependencies:
288
-
289
- ```bash
290
- uv sync --extra test
291
- ```
292
-
293
- Run the tests and example:
294
-
295
- ```bash
296
- uv run pytest
297
- uv run python examples/basic.py
298
- ```
299
-
300
- Build the source distribution and wheel:
301
-
302
- ```bash
303
- uv build
304
- ```
305
-
306
450
  ## License
307
451
 
308
452
  MIT. See [`LICENSE`](LICENSE).
@@ -4,10 +4,10 @@
4
4
  that displays a full-screen loading overlay while a Dash application performs
5
5
  its initial browser-side startup.
6
6
 
7
- The overlay is injected into the final HTML document with `hooks.index`, so it
8
- is visible before Dash and React mount the application layout. The packaged CSS
9
- and JavaScript are registered with `hooks.stylesheet` and `hooks.script`; an app
10
- does not need to copy assets or replace Dash's `index_string`.
7
+ The overlay, CSS, and JavaScript are injected into the final HTML document with
8
+ `hooks.index`, so they are available before Dash and React mount the application
9
+ layout without additional startup resource requests. An app does not need to
10
+ copy assets or replace Dash's `index_string`.
11
11
 
12
12
  ## Features
13
13
 
@@ -16,8 +16,10 @@ does not need to copy assets or replace Dash's `index_string`.
16
16
  - Waits for real rendered content and optional app-specific readiness selectors.
17
17
  - Can wait for lazy-loading placeholders to disappear.
18
18
  - Includes a timeout fallback, minimum display time, and fade-out transition.
19
- - Supports light and dark themes, reduced-motion preferences, custom colors,
20
- custom spinner geometry, and trusted custom loader markup.
19
+ - Inlines its small startup CSS and JavaScript, avoiding two additional requests.
20
+ - Resolves light and dark themes before first paint from Dash component
21
+ persistence, Tailwind root classes, Mantine color-scheme state, or the
22
+ operating-system preference.
21
23
  - Exposes a small browser API and emits a completion event.
22
24
  - Requires no changes to the app layout or callbacks.
23
25
 
@@ -33,7 +35,7 @@ discovery, resource hooks, and the index hook described in the official
33
35
  ## Installation
34
36
 
35
37
  ```bash
36
- pip install dash-startup-loading-plugin
38
+ pip install "dash-startup-loading-plugin>=0.3.0"
37
39
  ```
38
40
 
39
41
  The package declares the following entry point:
@@ -48,6 +50,27 @@ package therefore enables the default startup overlay for Dash applications in
48
50
  that Python environment; an explicit import is only needed when changing its
49
51
  configuration or using its Python API.
50
52
 
53
+ ## What's new in 0.3.0
54
+
55
+ - Adds `configure_antd()` with matching `#ffffff` and `#121212` loading
56
+ backgrounds plus explicit light/dark overrides.
57
+ - Adds `configure_mantine()` with theme defaults sourced from Dash Mantine
58
+ Components and its pre-render color-scheme hook.
59
+ - Updates the Dash Ant Design example for the structured
60
+ `ConfigProvider.theme.algorithm` API.
61
+ - Adds a Dash Mantine Components example with persisted theme switching.
62
+
63
+ ## What's new in 0.2.0
64
+
65
+ - Resolves the loading background before first paint from a persisted
66
+ `dash_antd_components.ConfigProvider.theme`.
67
+ - Supports Tailwind's `html.dark` and `html.light` classes.
68
+ - Supports Dash Mantine Components' `data-mantine-color-scheme` attribute and
69
+ `mantine-color-scheme-value` localStorage entry.
70
+ - Adds `theme_mode` and `dash_theme_component_id` configuration.
71
+ - Keeps the startup CSS and JavaScript inline, so theme detection does not add
72
+ network requests before Dash mounts.
73
+
51
74
  ## Quick start
52
75
 
53
76
  The defaults work without any plugin-specific code:
@@ -75,25 +98,33 @@ from dash import Dash, html
75
98
  from dash_startup_loading_plugin import configure
76
99
 
77
100
  configure(
78
- required_selectors=["#page-header", "#sidebar-menu"],
101
+ required_selectors=["#usage-header", "#usage-sidebar-menu"],
79
102
  pending_selector="[data-dac-async-placeholder]",
80
103
  timeout_ms=6000,
81
- minimum_display_ms=200,
82
104
  fade_duration_ms=160,
83
- color="#1677ff",
84
- dark_color="#4096ff",
85
105
  )
86
106
 
87
107
  app = Dash(__name__)
88
108
  app.layout = html.Div(
89
109
  [
90
- html.Header("Dashboard", id="page-header"),
91
- html.Nav("Navigation", id="sidebar-menu"),
110
+ html.Header("Dashboard", id="usage-header"),
111
+ html.Nav("Navigation", id="usage-sidebar-menu"),
92
112
  ]
93
113
  )
94
114
  ```
95
115
 
96
- See [`examples/basic.py`](examples/basic.py) for a runnable example.
116
+ Runnable examples:
117
+
118
+ - [`examples/basic.py`](examples/basic.py): Dash Ant Design theme persistence.
119
+ - [`examples/mantine_theme.py`](examples/mantine_theme.py):
120
+ Dash Mantine Components with a persisted light/dark theme switch.
121
+
122
+ Run the Mantine example with:
123
+
124
+ ```bash
125
+ pip install -e ".[mantine]"
126
+ python examples/mantine_theme.py
127
+ ```
97
128
 
98
129
  ## Readiness behavior
99
130
 
@@ -136,14 +167,133 @@ immutable `StartupLoadingConfig` instance.
136
167
  | `dark_background` | `"#0f0f0f"` | Dark-theme background color. |
137
168
  | `color` | `"#1677ff"` | Light-theme spinner/current color. |
138
169
  | `dark_color` | `"#4096ff"` | Dark-theme spinner/current color. |
170
+ | `theme_mode` | `"auto"` | Startup theme policy: `"auto"`, `"light"`, or `"dark"`. Auto follows persisted or active app state, then the operating-system preference. |
171
+ | `dash_theme_component_id` | `None` | Preferred Dash component ID when reading a persisted `theme` prop. When omitted, the first compatible persisted theme is used. |
139
172
  | `spinner_size_px` | `28` | Default spinner width and height in pixels. |
140
173
  | `spinner_stroke_px` | `3` | Default spinner stroke width in pixels. |
141
174
  | `hide_default_loading` | `True` | Hide Dash's built-in initial `._dash-loading` indicator while the overlay is present. |
142
175
  | `custom_loader_html` | `None` | Trusted HTML that replaces the default spinner. |
143
176
 
144
- The default stylesheet recognizes `html.dark` and `html.light`. When neither
145
- class forces a theme, it follows `prefers-color-scheme`. It also adjusts its
146
- animation when the user enables `prefers-reduced-motion`.
177
+ With `theme_mode="auto"`, the inline head bootstrap resolves the startup theme
178
+ in this order:
179
+
180
+ 1. The persisted Dash `theme` for `dash_theme_component_id`, when configured.
181
+ 2. An existing `html.dark` or `html.light` class, including Tailwind's manual
182
+ dark-mode convention.
183
+ 3. `data-theme`, `data-color-scheme`, or `data-mantine-color-scheme` on
184
+ `<html>`.
185
+ 4. Other Dash local persistence entries for a component's `theme` prop. Set
186
+ `dash_theme_component_id` when an app contains more than one persisted
187
+ theme-capable component.
188
+ 5. Dash Mantine Components' `mantine-color-scheme-value` localStorage entry,
189
+ followed by the common `theme`, `color-theme`, and `color-scheme` keys.
190
+ 6. `prefers-color-scheme`.
191
+
192
+ The result is written to `data-dash-startup-loading-theme` before the body is
193
+ parsed. This isolates the overlay styling without changing classes or data
194
+ attributes owned by Tailwind, Dash Mantine Components, or the application.
195
+ The stylesheet also adjusts its animation for `prefers-reduced-motion`.
196
+
197
+ ### Dash Mantine Components
198
+
199
+ Dash Mantine Components 2.6 and later includes `ColorSchemeToggle`, which
200
+ switches the active color scheme without a callback and persists it in
201
+ `mantine-color-scheme-value`. The startup plugin reads that value before Dash
202
+ and React mount. To make the loading transition seamless, use Mantine's current
203
+ default dark body color for the overlay:
204
+
205
+ ```python
206
+ import dash_mantine_components as dmc
207
+ from dash_startup_loading_plugin import configure_mantine
208
+
209
+ configure_mantine()
210
+
211
+ app.layout = dmc.MantineProvider(
212
+ [
213
+ dmc.ColorSchemeToggle(
214
+ lightIcon=dmc.Text("☀"),
215
+ darkIcon=dmc.Text("☾"),
216
+ ),
217
+ dmc.Text("Application content", id="app-ready"),
218
+ ],
219
+ defaultColorScheme="auto",
220
+ )
221
+ ```
222
+
223
+ See
224
+ [`examples/mantine_theme.py`](examples/mantine_theme.py)
225
+ for the complete runnable example.
226
+
227
+ `configure_mantine()` keeps DMC optional. When used, it registers DMC's
228
+ pre-render color-scheme hook, disables the Dash Ant Design placeholder check,
229
+ and derives the light and dark loading backgrounds from DMC's active default
230
+ theme. Any explicit configuration still takes precedence:
231
+
232
+ ```python
233
+ configure_mantine(dark_background="#202020")
234
+ ```
235
+
236
+ ### Dash Ant Design persistence
237
+
238
+ Current `dash_antd_components.ConfigProvider.theme` accepts a structured theme
239
+ configuration whose `algorithm` is `"default"`, `"dark"`, `"compact"`, or an
240
+ array of those values. Persist a user-facing system/light/dark selector, resolve
241
+ the system preference in a clientside callback, and store the semantic choice
242
+ in the small conventional `localStorage["theme"]` value that the startup plugin
243
+ reads before Dash mounts:
244
+
245
+ ```python
246
+ import dash_antd_components as dac
247
+ from dash import Input, Output, clientside_callback
248
+ from dash_startup_loading_plugin import configure_antd
249
+
250
+ configure_antd()
251
+
252
+ provider = dac.ConfigProvider(
253
+ [
254
+ app_content,
255
+ dac.Segmented(
256
+ id="theme-mode",
257
+ options=["system", "light", "dark"],
258
+ value="system",
259
+ persistence=True,
260
+ persisted_props=["value"],
261
+ persistence_type="local",
262
+ ),
263
+ ],
264
+ id="theme-provider",
265
+ theme={"algorithm": "default"},
266
+ )
267
+
268
+ clientside_callback(
269
+ """function(mode) {
270
+ localStorage.setItem("theme", JSON.stringify(mode));
271
+ const dark = mode === "dark" || (
272
+ mode === "system"
273
+ && window.matchMedia("(prefers-color-scheme: dark)").matches
274
+ );
275
+ return {algorithm: dark ? "dark" : "default"};
276
+ }""",
277
+ Output("theme-provider", "theme"),
278
+ Input("theme-mode", "value"),
279
+ )
280
+ ```
281
+
282
+ The selector owns the semantic `"system"` state; `ConfigProvider` receives only
283
+ the algorithms allowed by its current API. `configure_antd()` uses `#ffffff`
284
+ and `#121212`, matching the component library's default light and dark
285
+ backgrounds. If the application customizes either background, pass the same
286
+ values explicitly:
287
+
288
+ ```python
289
+ configure_antd(
290
+ background="#f5f5f5",
291
+ dark_background="#202020",
292
+ )
293
+ ```
294
+
295
+ See
296
+ [`examples/basic.py`](examples/basic.py) for the complete switcher.
147
297
 
148
298
  ### Custom loader markup
149
299
 
@@ -170,12 +320,18 @@ configuration. Never populate it with user input.
170
320
  from dash_startup_loading_plugin import (
171
321
  StartupLoadingConfig,
172
322
  configure,
323
+ configure_antd,
324
+ configure_mantine,
173
325
  get_config,
174
326
  reset_config,
175
327
  )
176
328
  ```
177
329
 
178
330
  - `configure(**changes)` validates and applies a partial configuration update.
331
+ - `configure_antd(**changes)` matches the loading backgrounds to Dash Ant
332
+ Design's light and dark themes and accepts explicit overrides.
333
+ - `configure_mantine(**changes)` applies DMC theme defaults and registers DMC's
334
+ pre-render color-scheme hook.
179
335
  - `get_config()` returns the current immutable configuration.
180
336
  - `reset_config()` restores all defaults. It is primarily useful in tests.
181
337
  - `StartupLoadingConfig` is the frozen dataclass containing all options.
@@ -225,11 +381,18 @@ configure(
225
381
  )
226
382
  ```
227
383
 
228
- The plugin preserves Dash's normal index template, injects the overlay directly
229
- after the opening `<body>` tag, and registers its versioned package assets via
230
- Dash Hooks. The index hook uses priority `100`, so it runs before lower-priority
231
- index hooks. If multiple hooks share the same priority, Dash does not guarantee
232
- their relative order.
384
+ The plugin preserves Dash's normal index template, injects its stylesheet before
385
+ `</head>`, and inserts the overlay followed by its startup script directly after
386
+ the opening `<body>` tag. The source CSS and JavaScript remain package resources
387
+ for maintainability, but the browser receives them inline and makes no separate
388
+ request for either file. The index hook uses priority `100`, so it runs before
389
+ lower-priority index hooks. If multiple hooks share the same priority, Dash does
390
+ not guarantee their relative order.
391
+
392
+ Because the resources are inline, applications with a strict Content Security
393
+ Policy must permit the injected style and script, or add nonce support in a
394
+ customized deployment. The previous external-resource form is more suitable
395
+ when a policy forbids all inline code.
233
396
 
234
397
  ## Scope and process model
235
398
 
@@ -266,27 +429,6 @@ This is expected with automatic `dash_hooks` discovery. Use a dedicated virtual
266
429
  environment, uninstall the package where it is not wanted, or call
267
430
  `configure(enabled=False)` before constructing those Dash apps.
268
431
 
269
- ## Development
270
-
271
- Clone the repository, then install the project and test dependencies:
272
-
273
- ```bash
274
- uv sync --extra test
275
- ```
276
-
277
- Run the tests and example:
278
-
279
- ```bash
280
- uv run pytest
281
- uv run python examples/basic.py
282
- ```
283
-
284
- Build the source distribution and wheel:
285
-
286
- ```bash
287
- uv build
288
- ```
289
-
290
432
  ## License
291
433
 
292
434
  MIT. See [`LICENSE`](LICENSE).
@@ -4,25 +4,28 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dash-startup-loading-plugin"
7
- version = "0.1.0"
7
+ version = "0.3.0"
8
8
  description = "A configurable full-screen startup loading overlay for Dash apps, packaged as a Dash Hooks plugin."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
11
11
  authors = [
12
12
  { name = "Ethan Zhang", email = "ethan.zhang2016@gmail.com" }
13
13
  ]
14
- keywords = ["dash", "plotly", "loading", "plugin", "hooks"]
14
+ keywords = ["dash", "plotly", "loading", "plugin"]
15
15
  classifiers = ["Framework :: Dash"]
16
16
  license = "MIT"
17
17
  license-files = ["LICENSE"]
18
18
  dependencies = [
19
- "dash>=3.0.3",
19
+ "dash==4.4.1",
20
20
  ]
21
21
 
22
22
  [project.optional-dependencies]
23
23
  test = [
24
24
  "pytest>=8",
25
25
  ]
26
+ mantine = [
27
+ "dash-mantine-components>=2.6.0",
28
+ ]
26
29
 
27
30
  [project.entry-points."dash_hooks"]
28
31
  dash_startup_loading_plugin = "dash_startup_loading_plugin"