nightshade-api 0.51.0

Procedural high level API for the nightshade game engine
Documentation
//! Assembles and injects the component stylesheet, wrapped in an
//! `@layer nightshade` cascade layer so app CSS always wins.

use leptos::prelude::*;

/// Concatenate every component stylesheet, wrapped in an
/// `@layer nightshade { ... }` cascade layer.
pub fn stylesheet() -> String {
    let mut css = String::new();
    css.push_str(include_str!("../../css/core.css"));
    css.push_str(include_str!("../../css/forms.css"));
    css.push_str(include_str!("../../css/menus.css"));
    css.push_str(include_str!("../../css/palette.css"));
    css.push_str(include_str!("../../css/code_editor.css"));
    css.push_str(include_str!("../../css/table.css"));
    css.push_str(include_str!("../../css/tree.css"));
    css.push_str(include_str!("../../css/inspector.css"));
    css.push_str(include_str!("../../css/dock.css"));
    css.push_str(include_str!("../../css/overlays.css"));
    css.push_str(include_str!("../../css/virtual_list.css"));
    css.push_str(include_str!("../../css/diff.css"));
    css.push_str(include_str!("../../css/drag.css"));
    css.push_str(include_str!("../../css/undo_tree.css"));
    css.push_str(include_str!("../../css/jump.css"));
    css.push_str(include_str!("../../css/terminal.css"));
    css.push_str(include_str!("../../css/workspace.css"));
    css.push_str(include_str!("../../css/code_surface.css"));
    css.push_str(include_str!("../../css/disclosure.css"));
    css.push_str(include_str!("../../css/status_bar.css"));
    css.push_str(include_str!("../../css/toolbar.css"));
    css.push_str(include_str!("../../css/log.css"));
    css.push_str(include_str!("../../css/markdown.css"));
    css.push_str(include_str!("../../css/search_list.css"));
    css.push_str(include_str!("../../css/asset_grid.css"));
    css.push_str(include_str!("../../css/list_editor.css"));
    css.push_str(include_str!("../../css/chat.css"));
    css.push_str(include_str!("../../css/dynamic_form.css"));
    css.push_str(include_str!("../../css/viewport.css"));
    format!("@layer nightshade {{\n{css}\n}}\n")
}

const STYLE_ID: &str = "nightshade-styles";

fn inject() {
    let Some(document) = web_sys::window().and_then(|window| window.document()) else {
        return;
    };
    if document.get_element_by_id(STYLE_ID).is_some() {
        return;
    }
    let Some(head) = document.head() else {
        return;
    };
    let Ok(element) = document.create_element("style") else {
        return;
    };
    let _ = element.set_attribute("id", STYLE_ID);
    element.set_text_content(Some(&stylesheet()));
    let _ = head.append_child(&element);
}

/// Injects the [`stylesheet`] into `<head>` once (idempotent by element id).
/// Render this near the root of your app.
#[component]
pub fn UiStyles() -> impl IntoView {
    inject();
}