Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@
- three: 0.168.0 ([MIT](https://opensource.org/licenses/MIT))
- tween: 25.0.0 ([MIT](https://opensource.org/licenses/MIT))
- vanilla-jsoneditor: 0.23.8 ([ISC](https://opensource.org/licenses/ISC))
- unocss_runtime: 66.1.4 ([MIT](https://opensource.org/licenses/MIT))
- unocss_reset: 66.1.4 ([MIT](https://opensource.org/licenses/MIT))
3 changes: 2 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ def _status():


# NOTE: do not reload on fly.io (see https://github.com/zauberzeug/nicegui/discussions/1720#discussioncomment-7288741)
ui.run(uvicorn_reload_includes='*.py, *.css, *.html', reload=not on_fly, reconnect_timeout=10.0)
ui.run(uvicorn_reload_includes='*.py, *.css, *.html', reload=not on_fly,
reconnect_timeout=10.0, tailwind=False, unocss_preset='wind3')
5 changes: 5 additions & 0 deletions nicegui/app/app_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class AppConfig:
message_history_length: int = field(init=False)
cache_control_directives: str = field(init=False)
tailwind: bool = field(init=False)
unocss_preset: Optional[Literal['mini', 'wind3', 'wind4']] = field(init=False)
prod_js: bool = field(init=False)
show_welcome_message: bool = field(init=False)
_has_run_config: bool = False
Expand All @@ -52,10 +53,13 @@ def add_run_config(self,
message_history_length: int,
cache_control_directives: str = 'public, max-age=31536000, immutable, stale-while-revalidate=31536000',
tailwind: bool,
unocss_preset: Optional[Literal['mini', 'wind3', 'wind4']] = None,
prod_js: bool,
show_welcome_message: bool,
) -> None:
"""Add the run config to the app config."""
if unocss_preset is not None and tailwind:
raise ValueError('unocss_preset and tailwind are mutually exclusive')
self.reload = reload
self.title = title
self.viewport = viewport
Expand All @@ -67,6 +71,7 @@ def add_run_config(self,
self.message_history_length = message_history_length
self.cache_control_directives = cache_control_directives
self.tailwind = tailwind
self.unocss_preset = unocss_preset
self.prod_js = prod_js
self.show_welcome_message = show_welcome_message
self._has_run_config = True
Expand Down
11 changes: 11 additions & 0 deletions nicegui/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ def build_response(self, request: Request, status_code: int = 200) -> Response:
'translations': translations.get(self.page.resolve_language(), translations['en-US']),
'prefix': prefix,
'tailwind': core.app.config.tailwind,
'unocss': core.app.config.unocss_preset is not None,
'unocss_filename': {
'mini': 'preset-mini',
'wind3': 'preset-wind', # until upstream renames this to preset-wind3.css, then update this
'wind4': 'preset-wind4',
}.get(core.app.config.unocss_preset),
'unocss_initline': {
'mini': '() => window.__unocss_runtime.presets.presetMini()',
'wind3': '() => window.__unocss_runtime.presets.presetWind()', # until upstream renames this to presetWind3()
'wind4': '() => window.__unocss_runtime.presets.presetWind4()',
}.get(core.app.config.unocss_preset),
'prod_js': core.app.config.prod_js,
'socket_io_js_query_params': socket_io_js_query_params,
'socket_io_js_extra_headers': core.app.config.socket_io_js_extra_headers,
Expand Down
4 changes: 4 additions & 0 deletions nicegui/elements/dark_mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default {
if (this.value) document.body.classList.add("dark");
else document.body.classList.remove("dark");
}
if (window.__unocss) {
window.nicegui_unocss_dark = this.value;
updateDarkMode();
}
},
},
props: {
Expand Down
32 changes: 32 additions & 0 deletions nicegui/static/nicegui.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ let mounted_app = undefined;
const loaded_libraries = new Set();
const loaded_components = new Set();

const allClassesFromElements = new Set();

function parseElements(raw_elements) {
return JSON.parse(
raw_elements
Expand Down Expand Up @@ -319,9 +321,31 @@ window.onbeforeunload = function () {
sessionStorage.__nicegui_tab_closed = "true";
};

async function generateStylesFromClasses(classes) {
if (window.__unocss_runtime === undefined) return;
const div = document.createElement("div");
div.className = Array.from(classes).join(" ");
const html = div.outerHTML;
await window.__unocss_runtime.extract(html);
// Wait until the style elements have been moved
await new Promise((resolve) => {
document.querySelectorAll("style[data-unocss-runtime-layer]:not([data-nicegui-moved])").forEach((style) => {
document.head.appendChild(style);
style.setAttribute("data-nicegui-moved", "true");
});
resolve();
});
}

function createApp(elements, options) {
Object.entries(elements).forEach(([_, element]) => replaceUndefinedAttributes(element));
setInterval(() => ack(), 3000);
Object.values(elements)
.flatMap((element) => element.class)
.forEach((c) => allClassesFromElements.add(c));
generateStylesFromClasses(allClassesFromElements).then(() => {
document.getElementById("app").style.removeProperty("display");
});
return (app = Vue.createApp({
data() {
return {
Expand Down Expand Up @@ -385,6 +409,14 @@ function createApp(elements, options) {
.map(([_, element]) => loadDependencies(element, options.prefix, options.version));
await Promise.all(loadPromises);

const originalClassesCount = allClassesFromElements.size;
Object.values(msg)
.flatMap((element) => element?.class || [])
.forEach((c) => allClassesFromElements.add(c));
if (allClassesFromElements.size > originalClassesCount) {
await generateStylesFromClasses(allClassesFromElements);
}

for (const [id, element] of Object.entries(msg)) {
if (element === null) {
delete this.elements[id];
Expand Down
Loading