dash-startup-loading-plugin 1.0.2__tar.gz → 1.0.4__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 (31) hide show
  1. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/MANIFEST.in +1 -0
  2. {dash_startup_loading_plugin-1.0.2/src/dash_startup_loading_plugin.egg-info → dash_startup_loading_plugin-1.0.4}/PKG-INFO +37 -9
  3. {dash_startup_loading_plugin-1.0.2/src/dash_startup_loading_plugin → dash_startup_loading_plugin-1.0.4}/README.md +36 -8
  4. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/README.zh-CN.md +31 -7
  5. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/pyproject.toml +1 -1
  6. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4/src/dash_startup_loading_plugin}/README.md +36 -8
  7. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/README.zh-CN.md +31 -7
  8. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/__init__.py +1 -1
  9. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/plugin.py +1 -1
  10. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/resources/theme.js +1 -1
  11. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4/src/dash_startup_loading_plugin.egg-info}/PKG-INFO +37 -9
  12. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/tests/test_documentation.py +3 -0
  13. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/tests/test_plugin.py +25 -0
  14. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/LICENSE +0 -0
  15. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/setup.cfg +0 -0
  16. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/__init__.py +0 -0
  17. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/__main__.py +0 -0
  18. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/antd.py +0 -0
  19. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/basic.py +0 -0
  20. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/cli.py +0 -0
  21. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/fac.py +0 -0
  22. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/mantine.py +0 -0
  23. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/examples/shared.py +0 -0
  24. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/resources/loading.css +0 -0
  25. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin/resources/loading.js +0 -0
  26. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin.egg-info/SOURCES.txt +0 -0
  27. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin.egg-info/dependency_links.txt +0 -0
  28. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin.egg-info/entry_points.txt +0 -0
  29. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin.egg-info/requires.txt +0 -0
  30. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/src/dash_startup_loading_plugin.egg-info/top_level.txt +0 -0
  31. {dash_startup_loading_plugin-1.0.2 → dash_startup_loading_plugin-1.0.4}/tests/test_examples.py +0 -0
@@ -1 +1,2 @@
1
1
  include README.zh-CN.md
2
+ include README.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dash-startup-loading-plugin
3
- Version: 1.0.2
3
+ Version: 1.0.4
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
@@ -34,7 +34,7 @@ document.
34
34
  ## Installation
35
35
 
36
36
  ```bash
37
- pip install "dash-startup-loading-plugin>=1.0.2"
37
+ pip install "dash-startup-loading-plugin>=1.0.4"
38
38
  ```
39
39
 
40
40
  Dash discovers the plugin through its `dash_hooks` entry point. Installing the
@@ -62,6 +62,10 @@ if __name__ == "__main__":
62
62
  app.run(debug=True)
63
63
  ```
64
64
 
65
+ By default, the overlay only replaces Dash's built-in `._dash-loading`
66
+ animation and closes once Dash has rendered the application layout. Waiting
67
+ for lazy or asynchronous component placeholders is opt-in.
68
+
65
69
  Call `configure()` before creating `Dash` when custom behavior is needed:
66
70
 
67
71
  ```python
@@ -85,6 +89,30 @@ app.layout = html.Main(
85
89
  )
86
90
  ```
87
91
 
92
+ ### Theme behavior
93
+
94
+ With the default `theme_mode="auto"`, the startup overlay follows an explicit
95
+ application theme from, in order, the root HTML element (including Tailwind's
96
+ `dark`/`light` classes and common theme data attributes), a persisted Dash
97
+ theme component, or conventional theme keys in local storage. If the
98
+ application has not declared a theme preference, the overlay uses the light
99
+ theme; it does not infer a preference from the operating system.
100
+
101
+ Set the mode explicitly when the application does not expose its preference,
102
+ or when the loading screen should always use one theme:
103
+
104
+ ```python
105
+ configure(theme_mode="light") # or "dark"
106
+ ```
107
+
108
+ An application preference explicitly set to `"system"` or `"auto"` still
109
+ uses `prefers-color-scheme`. Use `dash_theme_component_id` to prefer one Dash
110
+ component when multiple persisted theme values exist:
111
+
112
+ ```python
113
+ configure(theme_mode="auto", dash_theme_component_id="theme-provider")
114
+ ```
115
+
88
116
  ## Component-library integrations
89
117
 
90
118
  Component libraries are not dependencies of this package. Install only the
@@ -180,16 +208,16 @@ The overlay closes when:
180
208
  1. `root_selector` exists and no longer contains `._dash-loading`.
181
209
  2. The root contains rendered content.
182
210
  3. Every `required_selectors` entry exists.
183
- 4. No `pending_selector` node remains under the root.
211
+ 4. If `pending_selector` is configured, no matching node remains under the root.
184
212
  5. The conditions remain true for two animation frames.
185
213
 
186
214
  `timeout_ms` is a forced-dismiss fallback. `minimum_display_ms` applies to
187
215
  ready and manual dismissal, but does not delay a timeout.
188
216
 
189
- `pending_selector` delays dismissal while any matching element remains inside
190
- `root_selector`. It is useful for lazy or asynchronous placeholders that are
191
- mounted before the real content. Set it to an application-specific CSS
192
- selector, or use `None` when no pending-node check is needed:
217
+ `pending_selector` optionally delays dismissal while any matching element
218
+ remains inside `root_selector`. It is useful for lazy or asynchronous
219
+ placeholders that are mounted before the real content. The check is disabled
220
+ by default; opt in with an application-specific CSS selector:
193
221
 
194
222
  ```python
195
223
  configure(pending_selector="[data-async-placeholder]")
@@ -208,7 +236,7 @@ configure(pending_selector=None)
208
236
  | `aria_label` | `"Loading"` | Accessible status label. |
209
237
  | `root_selector` | `"#react-entry-point"` | Root observed for rendered content. |
210
238
  | `required_selectors` | `("#react-entry-point",)` | Selectors that must exist before dismissal. |
211
- | `pending_selector` | `"[data-dac-async-placeholder]"` | Selector checked under `root_selector`; dismissal waits until all matches disappear. Use `None` to disable. |
239
+ | `pending_selector` | `None` | Optional selector checked under `root_selector`; when configured, dismissal waits until all matches disappear. |
212
240
  | `timeout_ms` | `6000` | Forced-dismiss timeout; use `None` to disable. |
213
241
  | `minimum_display_ms` | `0` | Minimum display time. |
214
242
  | `fade_duration_ms` | `160` | Fade-out duration. |
@@ -217,7 +245,7 @@ configure(pending_selector=None)
217
245
  | `dark_background` | `"#0f0f0f"` | Dark background. |
218
246
  | `color` | `"#1677ff"` | Light spinner color. |
219
247
  | `dark_color` | `"#4096ff"` | Dark spinner color. |
220
- | `theme_mode` | `"auto"` | `"auto"`, `"light"`, or `"dark"`. |
248
+ | `theme_mode` | `"auto"` | `"auto"` detects application theme signals and otherwise uses light; `"light"` and `"dark"` force a mode. |
221
249
  | `dash_theme_component_id` | `None` | Preferred persisted Dash theme component. |
222
250
  | `spinner_size_px` | `28` | Spinner width and height. |
223
251
  | `spinner_stroke_px` | `3` | Spinner stroke width. |
@@ -20,7 +20,7 @@ document.
20
20
  ## Installation
21
21
 
22
22
  ```bash
23
- pip install "dash-startup-loading-plugin>=1.0.2"
23
+ pip install "dash-startup-loading-plugin>=1.0.4"
24
24
  ```
25
25
 
26
26
  Dash discovers the plugin through its `dash_hooks` entry point. Installing the
@@ -48,6 +48,10 @@ if __name__ == "__main__":
48
48
  app.run(debug=True)
49
49
  ```
50
50
 
51
+ By default, the overlay only replaces Dash's built-in `._dash-loading`
52
+ animation and closes once Dash has rendered the application layout. Waiting
53
+ for lazy or asynchronous component placeholders is opt-in.
54
+
51
55
  Call `configure()` before creating `Dash` when custom behavior is needed:
52
56
 
53
57
  ```python
@@ -71,6 +75,30 @@ app.layout = html.Main(
71
75
  )
72
76
  ```
73
77
 
78
+ ### Theme behavior
79
+
80
+ With the default `theme_mode="auto"`, the startup overlay follows an explicit
81
+ application theme from, in order, the root HTML element (including Tailwind's
82
+ `dark`/`light` classes and common theme data attributes), a persisted Dash
83
+ theme component, or conventional theme keys in local storage. If the
84
+ application has not declared a theme preference, the overlay uses the light
85
+ theme; it does not infer a preference from the operating system.
86
+
87
+ Set the mode explicitly when the application does not expose its preference,
88
+ or when the loading screen should always use one theme:
89
+
90
+ ```python
91
+ configure(theme_mode="light") # or "dark"
92
+ ```
93
+
94
+ An application preference explicitly set to `"system"` or `"auto"` still
95
+ uses `prefers-color-scheme`. Use `dash_theme_component_id` to prefer one Dash
96
+ component when multiple persisted theme values exist:
97
+
98
+ ```python
99
+ configure(theme_mode="auto", dash_theme_component_id="theme-provider")
100
+ ```
101
+
74
102
  ## Component-library integrations
75
103
 
76
104
  Component libraries are not dependencies of this package. Install only the
@@ -166,16 +194,16 @@ The overlay closes when:
166
194
  1. `root_selector` exists and no longer contains `._dash-loading`.
167
195
  2. The root contains rendered content.
168
196
  3. Every `required_selectors` entry exists.
169
- 4. No `pending_selector` node remains under the root.
197
+ 4. If `pending_selector` is configured, no matching node remains under the root.
170
198
  5. The conditions remain true for two animation frames.
171
199
 
172
200
  `timeout_ms` is a forced-dismiss fallback. `minimum_display_ms` applies to
173
201
  ready and manual dismissal, but does not delay a timeout.
174
202
 
175
- `pending_selector` delays dismissal while any matching element remains inside
176
- `root_selector`. It is useful for lazy or asynchronous placeholders that are
177
- mounted before the real content. Set it to an application-specific CSS
178
- selector, or use `None` when no pending-node check is needed:
203
+ `pending_selector` optionally delays dismissal while any matching element
204
+ remains inside `root_selector`. It is useful for lazy or asynchronous
205
+ placeholders that are mounted before the real content. The check is disabled
206
+ by default; opt in with an application-specific CSS selector:
179
207
 
180
208
  ```python
181
209
  configure(pending_selector="[data-async-placeholder]")
@@ -194,7 +222,7 @@ configure(pending_selector=None)
194
222
  | `aria_label` | `"Loading"` | Accessible status label. |
195
223
  | `root_selector` | `"#react-entry-point"` | Root observed for rendered content. |
196
224
  | `required_selectors` | `("#react-entry-point",)` | Selectors that must exist before dismissal. |
197
- | `pending_selector` | `"[data-dac-async-placeholder]"` | Selector checked under `root_selector`; dismissal waits until all matches disappear. Use `None` to disable. |
225
+ | `pending_selector` | `None` | Optional selector checked under `root_selector`; when configured, dismissal waits until all matches disappear. |
198
226
  | `timeout_ms` | `6000` | Forced-dismiss timeout; use `None` to disable. |
199
227
  | `minimum_display_ms` | `0` | Minimum display time. |
200
228
  | `fade_duration_ms` | `160` | Fade-out duration. |
@@ -203,7 +231,7 @@ configure(pending_selector=None)
203
231
  | `dark_background` | `"#0f0f0f"` | Dark background. |
204
232
  | `color` | `"#1677ff"` | Light spinner color. |
205
233
  | `dark_color` | `"#4096ff"` | Dark spinner color. |
206
- | `theme_mode` | `"auto"` | `"auto"`, `"light"`, or `"dark"`. |
234
+ | `theme_mode` | `"auto"` | `"auto"` detects application theme signals and otherwise uses light; `"light"` and `"dark"` force a mode. |
207
235
  | `dash_theme_component_id` | `None` | Preferred persisted Dash theme component. |
208
236
  | `spinner_size_px` | `28` | Spinner width and height. |
209
237
  | `spinner_stroke_px` | `3` | Spinner stroke width. |
@@ -18,7 +18,7 @@
18
18
  ## 安装
19
19
 
20
20
  ```bash
21
- pip install "dash-startup-loading-plugin>=1.0.2"
21
+ pip install "dash-startup-loading-plugin>=1.0.4"
22
22
  ```
23
23
 
24
24
  Dash 会通过 `dash_hooks` entry point 自动发现插件。安装后,默认 loading
@@ -46,6 +46,9 @@ if __name__ == "__main__":
46
46
  app.run(debug=True)
47
47
  ```
48
48
 
49
+ 默认情况下,遮罩只替换 Dash 自带的 `._dash-loading` 动画,并在 Dash
50
+ 渲染出应用布局后关闭。等待懒加载或异步组件的占位节点消失属于可选行为。
51
+
49
52
  如需自定义行为,请在创建 `Dash` 实例前调用 `configure()`:
50
53
 
51
54
  ```python
@@ -69,6 +72,27 @@ app.layout = html.Main(
69
72
  )
70
73
  ```
71
74
 
75
+ ### 主题行为
76
+
77
+ 默认的 `theme_mode="auto"` 会按顺序读取应用显式提供的主题:HTML 根节点
78
+ (包括 Tailwind 的 `dark`/`light` 类及常见主题 data 属性)、Dash 组件的
79
+ 持久化主题值,以及 local storage 中的常见主题键。如果应用没有声明主题
80
+ 偏好,loading 遮罩会使用亮色主题,不会根据操作系统配色自动推断。
81
+
82
+ 当应用没有暴露主题偏好,或 loading 页面需要固定主题时,可手动配置:
83
+
84
+ ```python
85
+ configure(theme_mode="light") # 或 "dark"
86
+ ```
87
+
88
+ 如果应用主题偏好明确设置为 `"system"` 或 `"auto"`,插件仍会读取
89
+ `prefers-color-scheme`。当页面中存在多个持久化主题值时,可用
90
+ `dash_theme_component_id` 指定优先读取的 Dash 组件:
91
+
92
+ ```python
93
+ configure(theme_mode="auto", dash_theme_component_id="theme-provider")
94
+ ```
95
+
72
96
  ## 组件库集成
73
97
 
74
98
  各组件库不是本插件的依赖。应用只需单独安装实际使用的组件库。
@@ -160,15 +184,15 @@ dash-startup-loading-plugin examples.dash \
160
184
  1. `root_selector` 已存在,且内部不再包含 `._dash-loading`。
161
185
  2. 根节点中已有实际渲染内容。
162
186
  3. `required_selectors` 中的所有选择器都已匹配到节点。
163
- 4. 根节点中已不存在匹配 `pending_selector` 的节点。
187
+ 4. 如果配置了 `pending_selector`,根节点中已不存在匹配它的节点。
164
188
  5. 上述状态连续保持两个动画帧。
165
189
 
166
190
  `timeout_ms` 是强制关闭的安全兜底。`minimum_display_ms` 适用于正常就绪和
167
191
  手动关闭,但不会延迟 timeout。
168
192
 
169
- `pending_selector` 用于在异步或懒加载占位节点仍存在时延迟关闭遮罩。它只会
170
- 在 `root_selector` 内查找匹配节点。可以设置为应用自己的 CSS 选择器;如果
171
- 不需要检查占位节点,请设置为 `None`:
193
+ `pending_selector` 可用于在异步或懒加载占位节点仍存在时延迟关闭遮罩。它只会
194
+ 在 `root_selector` 内查找匹配节点。该检查默认关闭;如需等待异步组件加载完成,
195
+ 请显式设置为应用自己的 CSS 选择器:
172
196
 
173
197
  ```python
174
198
  configure(pending_selector="[data-async-placeholder]")
@@ -186,7 +210,7 @@ configure(pending_selector=None)
186
210
  | `aria_label` | `"Loading"` | 无障碍状态标签。 |
187
211
  | `root_selector` | `"#react-entry-point"` | 用于观察渲染内容的根节点。 |
188
212
  | `required_selectors` | `("#react-entry-point",)` | 关闭遮罩前必须存在的节点选择器。 |
189
- | `pending_selector` | `"[data-dac-async-placeholder]"` | 在 `root_selector` 内检查;所有匹配节点消失后才允许关闭。设置为 `None` 可禁用。 |
213
+ | `pending_selector` | `None` | 可选的根节点内选择器;配置后,所有匹配节点消失才允许关闭。 |
190
214
  | `timeout_ms` | `6000` | 强制关闭超时;设置为 `None` 可禁用。 |
191
215
  | `minimum_display_ms` | `0` | 最短显示时间。 |
192
216
  | `fade_duration_ms` | `160` | 淡出时长。 |
@@ -195,7 +219,7 @@ configure(pending_selector=None)
195
219
  | `dark_background` | `"#0f0f0f"` | 暗色背景。 |
196
220
  | `color` | `"#1677ff"` | 亮色 spinner 颜色。 |
197
221
  | `dark_color` | `"#4096ff"` | 暗色 spinner 颜色。 |
198
- | `theme_mode` | `"auto"` | 可选 `"auto"`、`"light"` 或 `"dark"`。 |
222
+ | `theme_mode` | `"auto"` | `"auto"` 自动检测应用主题,未检测到时使用亮色;`"light"` 和 `"dark"` 用于强制指定主题。 |
199
223
  | `dash_theme_component_id` | `None` | 优先读取主题状态的 Dash 持久化组件 ID。 |
200
224
  | `spinner_size_px` | `28` | Spinner 宽度和高度。 |
201
225
  | `spinner_stroke_px` | `3` | Spinner 描边宽度。 |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dash-startup-loading-plugin"
7
- version = "1.0.2"
7
+ version = "1.0.4"
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"
@@ -20,7 +20,7 @@ document.
20
20
  ## Installation
21
21
 
22
22
  ```bash
23
- pip install "dash-startup-loading-plugin>=1.0.2"
23
+ pip install "dash-startup-loading-plugin>=1.0.4"
24
24
  ```
25
25
 
26
26
  Dash discovers the plugin through its `dash_hooks` entry point. Installing the
@@ -48,6 +48,10 @@ if __name__ == "__main__":
48
48
  app.run(debug=True)
49
49
  ```
50
50
 
51
+ By default, the overlay only replaces Dash's built-in `._dash-loading`
52
+ animation and closes once Dash has rendered the application layout. Waiting
53
+ for lazy or asynchronous component placeholders is opt-in.
54
+
51
55
  Call `configure()` before creating `Dash` when custom behavior is needed:
52
56
 
53
57
  ```python
@@ -71,6 +75,30 @@ app.layout = html.Main(
71
75
  )
72
76
  ```
73
77
 
78
+ ### Theme behavior
79
+
80
+ With the default `theme_mode="auto"`, the startup overlay follows an explicit
81
+ application theme from, in order, the root HTML element (including Tailwind's
82
+ `dark`/`light` classes and common theme data attributes), a persisted Dash
83
+ theme component, or conventional theme keys in local storage. If the
84
+ application has not declared a theme preference, the overlay uses the light
85
+ theme; it does not infer a preference from the operating system.
86
+
87
+ Set the mode explicitly when the application does not expose its preference,
88
+ or when the loading screen should always use one theme:
89
+
90
+ ```python
91
+ configure(theme_mode="light") # or "dark"
92
+ ```
93
+
94
+ An application preference explicitly set to `"system"` or `"auto"` still
95
+ uses `prefers-color-scheme`. Use `dash_theme_component_id` to prefer one Dash
96
+ component when multiple persisted theme values exist:
97
+
98
+ ```python
99
+ configure(theme_mode="auto", dash_theme_component_id="theme-provider")
100
+ ```
101
+
74
102
  ## Component-library integrations
75
103
 
76
104
  Component libraries are not dependencies of this package. Install only the
@@ -166,16 +194,16 @@ The overlay closes when:
166
194
  1. `root_selector` exists and no longer contains `._dash-loading`.
167
195
  2. The root contains rendered content.
168
196
  3. Every `required_selectors` entry exists.
169
- 4. No `pending_selector` node remains under the root.
197
+ 4. If `pending_selector` is configured, no matching node remains under the root.
170
198
  5. The conditions remain true for two animation frames.
171
199
 
172
200
  `timeout_ms` is a forced-dismiss fallback. `minimum_display_ms` applies to
173
201
  ready and manual dismissal, but does not delay a timeout.
174
202
 
175
- `pending_selector` delays dismissal while any matching element remains inside
176
- `root_selector`. It is useful for lazy or asynchronous placeholders that are
177
- mounted before the real content. Set it to an application-specific CSS
178
- selector, or use `None` when no pending-node check is needed:
203
+ `pending_selector` optionally delays dismissal while any matching element
204
+ remains inside `root_selector`. It is useful for lazy or asynchronous
205
+ placeholders that are mounted before the real content. The check is disabled
206
+ by default; opt in with an application-specific CSS selector:
179
207
 
180
208
  ```python
181
209
  configure(pending_selector="[data-async-placeholder]")
@@ -194,7 +222,7 @@ configure(pending_selector=None)
194
222
  | `aria_label` | `"Loading"` | Accessible status label. |
195
223
  | `root_selector` | `"#react-entry-point"` | Root observed for rendered content. |
196
224
  | `required_selectors` | `("#react-entry-point",)` | Selectors that must exist before dismissal. |
197
- | `pending_selector` | `"[data-dac-async-placeholder]"` | Selector checked under `root_selector`; dismissal waits until all matches disappear. Use `None` to disable. |
225
+ | `pending_selector` | `None` | Optional selector checked under `root_selector`; when configured, dismissal waits until all matches disappear. |
198
226
  | `timeout_ms` | `6000` | Forced-dismiss timeout; use `None` to disable. |
199
227
  | `minimum_display_ms` | `0` | Minimum display time. |
200
228
  | `fade_duration_ms` | `160` | Fade-out duration. |
@@ -203,7 +231,7 @@ configure(pending_selector=None)
203
231
  | `dark_background` | `"#0f0f0f"` | Dark background. |
204
232
  | `color` | `"#1677ff"` | Light spinner color. |
205
233
  | `dark_color` | `"#4096ff"` | Dark spinner color. |
206
- | `theme_mode` | `"auto"` | `"auto"`, `"light"`, or `"dark"`. |
234
+ | `theme_mode` | `"auto"` | `"auto"` detects application theme signals and otherwise uses light; `"light"` and `"dark"` force a mode. |
207
235
  | `dash_theme_component_id` | `None` | Preferred persisted Dash theme component. |
208
236
  | `spinner_size_px` | `28` | Spinner width and height. |
209
237
  | `spinner_stroke_px` | `3` | Spinner stroke width. |
@@ -18,7 +18,7 @@
18
18
  ## 安装
19
19
 
20
20
  ```bash
21
- pip install "dash-startup-loading-plugin>=1.0.2"
21
+ pip install "dash-startup-loading-plugin>=1.0.4"
22
22
  ```
23
23
 
24
24
  Dash 会通过 `dash_hooks` entry point 自动发现插件。安装后,默认 loading
@@ -46,6 +46,9 @@ if __name__ == "__main__":
46
46
  app.run(debug=True)
47
47
  ```
48
48
 
49
+ 默认情况下,遮罩只替换 Dash 自带的 `._dash-loading` 动画,并在 Dash
50
+ 渲染出应用布局后关闭。等待懒加载或异步组件的占位节点消失属于可选行为。
51
+
49
52
  如需自定义行为,请在创建 `Dash` 实例前调用 `configure()`:
50
53
 
51
54
  ```python
@@ -69,6 +72,27 @@ app.layout = html.Main(
69
72
  )
70
73
  ```
71
74
 
75
+ ### 主题行为
76
+
77
+ 默认的 `theme_mode="auto"` 会按顺序读取应用显式提供的主题:HTML 根节点
78
+ (包括 Tailwind 的 `dark`/`light` 类及常见主题 data 属性)、Dash 组件的
79
+ 持久化主题值,以及 local storage 中的常见主题键。如果应用没有声明主题
80
+ 偏好,loading 遮罩会使用亮色主题,不会根据操作系统配色自动推断。
81
+
82
+ 当应用没有暴露主题偏好,或 loading 页面需要固定主题时,可手动配置:
83
+
84
+ ```python
85
+ configure(theme_mode="light") # 或 "dark"
86
+ ```
87
+
88
+ 如果应用主题偏好明确设置为 `"system"` 或 `"auto"`,插件仍会读取
89
+ `prefers-color-scheme`。当页面中存在多个持久化主题值时,可用
90
+ `dash_theme_component_id` 指定优先读取的 Dash 组件:
91
+
92
+ ```python
93
+ configure(theme_mode="auto", dash_theme_component_id="theme-provider")
94
+ ```
95
+
72
96
  ## 组件库集成
73
97
 
74
98
  各组件库不是本插件的依赖。应用只需单独安装实际使用的组件库。
@@ -160,15 +184,15 @@ dash-startup-loading-plugin examples.dash \
160
184
  1. `root_selector` 已存在,且内部不再包含 `._dash-loading`。
161
185
  2. 根节点中已有实际渲染内容。
162
186
  3. `required_selectors` 中的所有选择器都已匹配到节点。
163
- 4. 根节点中已不存在匹配 `pending_selector` 的节点。
187
+ 4. 如果配置了 `pending_selector`,根节点中已不存在匹配它的节点。
164
188
  5. 上述状态连续保持两个动画帧。
165
189
 
166
190
  `timeout_ms` 是强制关闭的安全兜底。`minimum_display_ms` 适用于正常就绪和
167
191
  手动关闭,但不会延迟 timeout。
168
192
 
169
- `pending_selector` 用于在异步或懒加载占位节点仍存在时延迟关闭遮罩。它只会
170
- 在 `root_selector` 内查找匹配节点。可以设置为应用自己的 CSS 选择器;如果
171
- 不需要检查占位节点,请设置为 `None`:
193
+ `pending_selector` 可用于在异步或懒加载占位节点仍存在时延迟关闭遮罩。它只会
194
+ 在 `root_selector` 内查找匹配节点。该检查默认关闭;如需等待异步组件加载完成,
195
+ 请显式设置为应用自己的 CSS 选择器:
172
196
 
173
197
  ```python
174
198
  configure(pending_selector="[data-async-placeholder]")
@@ -186,7 +210,7 @@ configure(pending_selector=None)
186
210
  | `aria_label` | `"Loading"` | 无障碍状态标签。 |
187
211
  | `root_selector` | `"#react-entry-point"` | 用于观察渲染内容的根节点。 |
188
212
  | `required_selectors` | `("#react-entry-point",)` | 关闭遮罩前必须存在的节点选择器。 |
189
- | `pending_selector` | `"[data-dac-async-placeholder]"` | 在 `root_selector` 内检查;所有匹配节点消失后才允许关闭。设置为 `None` 可禁用。 |
213
+ | `pending_selector` | `None` | 可选的根节点内选择器;配置后,所有匹配节点消失才允许关闭。 |
190
214
  | `timeout_ms` | `6000` | 强制关闭超时;设置为 `None` 可禁用。 |
191
215
  | `minimum_display_ms` | `0` | 最短显示时间。 |
192
216
  | `fade_duration_ms` | `160` | 淡出时长。 |
@@ -195,7 +219,7 @@ configure(pending_selector=None)
195
219
  | `dark_background` | `"#0f0f0f"` | 暗色背景。 |
196
220
  | `color` | `"#1677ff"` | 亮色 spinner 颜色。 |
197
221
  | `dark_color` | `"#4096ff"` | 暗色 spinner 颜色。 |
198
- | `theme_mode` | `"auto"` | 可选 `"auto"`、`"light"` 或 `"dark"`。 |
222
+ | `theme_mode` | `"auto"` | `"auto"` 自动检测应用主题,未检测到时使用亮色;`"light"` 和 `"dark"` 用于强制指定主题。 |
199
223
  | `dash_theme_component_id` | `None` | 优先读取主题状态的 Dash 持久化组件 ID。 |
200
224
  | `spinner_size_px` | `28` | Spinner 宽度和高度。 |
201
225
  | `spinner_stroke_px` | `3` | Spinner 描边宽度。 |
@@ -5,7 +5,7 @@ from importlib.metadata import PackageNotFoundError, version
5
5
  try:
6
6
  __version__ = version("dash-startup-loading-plugin")
7
7
  except PackageNotFoundError: # pragma: no cover - source tree fallback
8
- __version__ = "1.0.2"
8
+ __version__ = "1.0.4"
9
9
 
10
10
  from .plugin import (
11
11
  StartupLoadingConfig,
@@ -37,7 +37,7 @@ class StartupLoadingConfig:
37
37
  aria_label: str = "Loading"
38
38
  root_selector: str = "#react-entry-point"
39
39
  required_selectors: tuple[str, ...] = ("#react-entry-point",)
40
- pending_selector: str | None = "[data-dac-async-placeholder]"
40
+ pending_selector: str | None = None
41
41
  timeout_ms: int | None = 6000
42
42
  minimum_display_ms: int = 0
43
43
  fade_duration_ms: int = 160
@@ -92,7 +92,7 @@
92
92
  theme = dashPersistenceTheme();
93
93
  }
94
94
  if (!theme) {
95
- theme = rootTheme() || dashPersistenceTheme() || conventionalStoredTheme() || "system";
95
+ theme = rootTheme() || dashPersistenceTheme() || conventionalStoredTheme() || "light";
96
96
  }
97
97
  if (theme === "system") {
98
98
  theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dash-startup-loading-plugin
3
- Version: 1.0.2
3
+ Version: 1.0.4
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
@@ -34,7 +34,7 @@ document.
34
34
  ## Installation
35
35
 
36
36
  ```bash
37
- pip install "dash-startup-loading-plugin>=1.0.2"
37
+ pip install "dash-startup-loading-plugin>=1.0.4"
38
38
  ```
39
39
 
40
40
  Dash discovers the plugin through its `dash_hooks` entry point. Installing the
@@ -62,6 +62,10 @@ if __name__ == "__main__":
62
62
  app.run(debug=True)
63
63
  ```
64
64
 
65
+ By default, the overlay only replaces Dash's built-in `._dash-loading`
66
+ animation and closes once Dash has rendered the application layout. Waiting
67
+ for lazy or asynchronous component placeholders is opt-in.
68
+
65
69
  Call `configure()` before creating `Dash` when custom behavior is needed:
66
70
 
67
71
  ```python
@@ -85,6 +89,30 @@ app.layout = html.Main(
85
89
  )
86
90
  ```
87
91
 
92
+ ### Theme behavior
93
+
94
+ With the default `theme_mode="auto"`, the startup overlay follows an explicit
95
+ application theme from, in order, the root HTML element (including Tailwind's
96
+ `dark`/`light` classes and common theme data attributes), a persisted Dash
97
+ theme component, or conventional theme keys in local storage. If the
98
+ application has not declared a theme preference, the overlay uses the light
99
+ theme; it does not infer a preference from the operating system.
100
+
101
+ Set the mode explicitly when the application does not expose its preference,
102
+ or when the loading screen should always use one theme:
103
+
104
+ ```python
105
+ configure(theme_mode="light") # or "dark"
106
+ ```
107
+
108
+ An application preference explicitly set to `"system"` or `"auto"` still
109
+ uses `prefers-color-scheme`. Use `dash_theme_component_id` to prefer one Dash
110
+ component when multiple persisted theme values exist:
111
+
112
+ ```python
113
+ configure(theme_mode="auto", dash_theme_component_id="theme-provider")
114
+ ```
115
+
88
116
  ## Component-library integrations
89
117
 
90
118
  Component libraries are not dependencies of this package. Install only the
@@ -180,16 +208,16 @@ The overlay closes when:
180
208
  1. `root_selector` exists and no longer contains `._dash-loading`.
181
209
  2. The root contains rendered content.
182
210
  3. Every `required_selectors` entry exists.
183
- 4. No `pending_selector` node remains under the root.
211
+ 4. If `pending_selector` is configured, no matching node remains under the root.
184
212
  5. The conditions remain true for two animation frames.
185
213
 
186
214
  `timeout_ms` is a forced-dismiss fallback. `minimum_display_ms` applies to
187
215
  ready and manual dismissal, but does not delay a timeout.
188
216
 
189
- `pending_selector` delays dismissal while any matching element remains inside
190
- `root_selector`. It is useful for lazy or asynchronous placeholders that are
191
- mounted before the real content. Set it to an application-specific CSS
192
- selector, or use `None` when no pending-node check is needed:
217
+ `pending_selector` optionally delays dismissal while any matching element
218
+ remains inside `root_selector`. It is useful for lazy or asynchronous
219
+ placeholders that are mounted before the real content. The check is disabled
220
+ by default; opt in with an application-specific CSS selector:
193
221
 
194
222
  ```python
195
223
  configure(pending_selector="[data-async-placeholder]")
@@ -208,7 +236,7 @@ configure(pending_selector=None)
208
236
  | `aria_label` | `"Loading"` | Accessible status label. |
209
237
  | `root_selector` | `"#react-entry-point"` | Root observed for rendered content. |
210
238
  | `required_selectors` | `("#react-entry-point",)` | Selectors that must exist before dismissal. |
211
- | `pending_selector` | `"[data-dac-async-placeholder]"` | Selector checked under `root_selector`; dismissal waits until all matches disappear. Use `None` to disable. |
239
+ | `pending_selector` | `None` | Optional selector checked under `root_selector`; when configured, dismissal waits until all matches disappear. |
212
240
  | `timeout_ms` | `6000` | Forced-dismiss timeout; use `None` to disable. |
213
241
  | `minimum_display_ms` | `0` | Minimum display time. |
214
242
  | `fade_duration_ms` | `160` | Fade-out duration. |
@@ -217,7 +245,7 @@ configure(pending_selector=None)
217
245
  | `dark_background` | `"#0f0f0f"` | Dark background. |
218
246
  | `color` | `"#1677ff"` | Light spinner color. |
219
247
  | `dark_color` | `"#4096ff"` | Dark spinner color. |
220
- | `theme_mode` | `"auto"` | `"auto"`, `"light"`, or `"dark"`. |
248
+ | `theme_mode` | `"auto"` | `"auto"` detects application theme signals and otherwise uses light; `"light"` and `"dark"` force a mode. |
221
249
  | `dash_theme_component_id` | `None` | Preferred persisted Dash theme component. |
222
250
  | `spinner_size_px` | `28` | Spinner width and height. |
223
251
  | `spinner_stroke_px` | `3` | Spinner stroke width. |
@@ -28,6 +28,9 @@ def test_readmes_use_current_selector_and_installation_examples():
28
28
  assert "usage-sidebar-menu" not in readme
29
29
  assert "dash-ant-design # Python 3.10+" not in readme
30
30
  assert "feffery-antd-components>=0.4.0" not in readme
31
+ assert 'theme_mode="auto"' in readme
32
+ assert 'theme_mode="light"' in readme
33
+ assert "dash_theme_component_id" in readme
31
34
 
32
35
 
33
36
  def test_readmes_link_to_each_other():
@@ -61,6 +61,15 @@ def test_injects_overlay_after_body_with_custom_attributes():
61
61
  assert result.count(" data-dash-loading ") == 1
62
62
  assert '<span class="dash-loading__spinner"' in result
63
63
  assert _data_config(result)["requiredSelectors"] == ["#react-entry-point"]
64
+ assert _data_config(result)["pendingSelector"] is None
65
+
66
+
67
+ def test_waiting_for_async_components_is_opt_in():
68
+ configure(pending_selector="[data-async-placeholder]")
69
+
70
+ result = _inject_overlay("<html><body><main></main></body></html>")
71
+
72
+ assert _data_config(result)["pendingSelector"] == "[data-async-placeholder]"
64
73
 
65
74
 
66
75
  def test_injection_is_idempotent_and_can_be_disabled():
@@ -202,6 +211,22 @@ def test_theme_bootstrap_supports_dash_tailwind_and_mantine_conventions():
202
211
  assert 'name === "system" || name === "auto"' in script
203
212
 
204
213
 
214
+ def test_theme_bootstrap_defaults_to_light_without_an_app_preference():
215
+ script = (
216
+ files("dash_startup_loading_plugin")
217
+ .joinpath("resources/theme.js")
218
+ .read_text(encoding="utf-8")
219
+ )
220
+
221
+ assert (
222
+ 'rootTheme() || dashPersistenceTheme() || conventionalStoredTheme() || "light"'
223
+ in script
224
+ )
225
+ assert 'conventionalStoredTheme() || "system"' not in script
226
+ assert 'theme === "system"' in script
227
+ assert 'matchMedia("(prefers-color-scheme: dark)")' in script
228
+
229
+
205
230
  def test_theme_bootstrap_serializes_component_id_and_explicit_mode():
206
231
  configure(theme_mode="dark", dash_theme_component_id="theme-provider")
207
232