use std::sync::Arc;
use leptos::prelude::*;
use orbital_data::{ChartFieldBinding, Dataset};
use orbital_macros::component_doc;
use orbital_theme::use_theme_options;
use crate::context::ChartKind;
use crate::engine::default_plot_inset;
use crate::{
AxisClickData, AxisDef, AxisHighlightConfig, ChartEmbedMode, ChartItemId, ChartMotion,
GridConfig, HighlightScope, LegendConfig, OrbitalChartPalette, OrbitalChartsTheme,
OverlayMount, PlotInset, SeriesDef, TooltipConfig,
};
use leptos::callback::Callback;
use super::chart_root::ChartRoot;
use super::resize::use_container_size;
#[component]
fn ResponsiveChartMeasuredHost(
node_ref: NodeRef<leptos::html::Div>,
measured: ReadSignal<(f64, f64)>,
width_override: Option<f64>,
height_override: Option<f64>,
dataset: Option<Dataset>,
binding: Option<ChartFieldBinding>,
margin: PlotInset,
skip_animation: Option<bool>,
motion: Option<ChartMotion>,
loading: bool,
series: Option<Vec<SeriesDef>>,
x_axis: Option<Vec<AxisDef>>,
y_axis: Option<Vec<AxisDef>>,
grid: Option<GridConfig>,
palette: Option<OrbitalChartPalette>,
highlight_scope: Option<HighlightScope>,
axis_highlight: Option<AxisHighlightConfig>,
legend: Option<LegendConfig>,
tooltip: Option<TooltipConfig>,
charts_theme: Option<OrbitalChartsTheme>,
highlighted_item: Option<RwSignal<Option<ChartItemId>>>,
on_highlight_change: Option<Callback<(Option<ChartItemId>,), ()>>,
on_legend_click: Option<Callback<(String,), ()>>,
on_item_click: Option<Callback<(ChartItemId,), ()>>,
on_axis_click: Option<Callback<(AxisClickData,), ()>>,
loading_view: Option<Arc<dyn Fn() -> AnyView + Send + Sync>>,
empty_view: Option<Arc<dyn Fn() -> AnyView + Send + Sync>>,
embed_mode: ChartEmbedMode,
overlay_mount: OverlayMount,
chart_kind: ChartKind,
#[prop(optional, into)] class: MaybeProp<String>,
#[prop(optional)] children: Option<Children>,
) -> impl IntoView {
let (mw, mh) = measured.get();
let width = width_override.unwrap_or(mw);
let height = height_override.unwrap_or(mh);
view! {
<div class="orb-chart-responsive-host" node_ref=node_ref>
<ChartRoot
class=class
dataset=dataset
binding=binding
width=width
height=height
margin=margin
skip_animation=skip_animation
motion=motion
loading=loading
series=series
x_axis=x_axis
y_axis=y_axis
grid=grid
palette=palette
highlight_scope=highlight_scope
axis_highlight=axis_highlight
legend=legend
tooltip=tooltip
charts_theme=charts_theme
highlighted_item=highlighted_item
on_highlight_change=on_highlight_change
on_item_click=on_item_click
on_axis_click=on_axis_click
on_legend_click=on_legend_click
loading_view=loading_view
empty_view=empty_view
embed_mode=embed_mode
overlay_mount=overlay_mount
chart_kind=chart_kind
>
{children.map(|c| c())}
</ChartRoot>
</div>
}
}
#[component_doc(
category = "Charts",
preview_slug = "chart-container-responsive",
preview_label = "Responsive Chart Container",
preview_icon = icondata::AiExpandOutlined,
)]
#[component]
pub fn ResponsiveChartContainer(
#[prop(default = None)]
series: Option<Vec<SeriesDef>>,
#[prop(default = None)]
dataset: Option<Dataset>,
#[prop(default = None)]
binding: Option<ChartFieldBinding>,
#[prop(default = None)]
x_axis: Option<Vec<AxisDef>>,
#[prop(default = None)]
y_axis: Option<Vec<AxisDef>>,
#[prop(default = None)]
width: Option<f64>,
#[prop(default = None)]
height: Option<f64>,
#[prop(default = None)]
margin: Option<PlotInset>,
#[prop(default = None)]
grid: Option<GridConfig>,
#[prop(default = None)]
loading: Option<bool>,
#[prop(default = None)]
skip_animation: Option<bool>,
#[prop(default = None)]
motion: Option<ChartMotion>,
#[prop(default = None)]
palette: Option<OrbitalChartPalette>,
#[prop(default = None)]
highlight_scope: Option<HighlightScope>,
#[prop(default = None)]
axis_highlight: Option<AxisHighlightConfig>,
#[prop(default = None)]
legend: Option<LegendConfig>,
#[prop(default = None)]
tooltip: Option<TooltipConfig>,
#[prop(default = None)]
charts_theme: Option<OrbitalChartsTheme>,
#[prop(default = None)]
highlighted_item: Option<RwSignal<Option<ChartItemId>>>,
#[prop(default = None)]
on_highlight_change: Option<Callback<(Option<ChartItemId>,), ()>>,
#[prop(default = None)]
on_legend_click: Option<Callback<(String,), ()>>,
#[prop(default = None)]
on_item_click: Option<Callback<(ChartItemId,), ()>>,
#[prop(default = None)]
on_axis_click: Option<Callback<(AxisClickData,), ()>>,
#[prop(optional, into)]
class: MaybeProp<String>,
#[prop(default = None)]
loading_view: Option<Arc<dyn Fn() -> AnyView + Send + Sync>>,
#[prop(default = None)]
empty_view: Option<Arc<dyn Fn() -> AnyView + Send + Sync>>,
#[prop(default = ChartEmbedMode::Inline)]
embed_mode: ChartEmbedMode,
#[prop(default = OverlayMount::ChartLocal)]
overlay_mount: OverlayMount,
#[prop(default = ChartKind::Cartesian)]
chart_kind: ChartKind,
#[prop(optional)]
children: Option<Children>,
) -> impl IntoView {
let host_ref = NodeRef::<leptos::html::Div>::new();
let fallback_w = width.unwrap_or(400.0);
let fallback_h = height.unwrap_or(300.0);
let measured = use_container_size(host_ref, (fallback_w, fallback_h));
let theme_options = use_theme_options();
let inset = margin.unwrap_or_else(|| default_plot_inset(theme_options.get_untracked().density));
let is_loading = loading.unwrap_or(false);
let root_class = class;
view! {
<ResponsiveChartMeasuredHost
node_ref=host_ref
measured=measured
width_override=width
height_override=height
class=root_class
dataset=dataset
binding=binding
margin=inset
skip_animation=skip_animation
motion=motion
loading=is_loading
series=series
x_axis=x_axis
y_axis=y_axis
grid=grid
palette=palette
highlight_scope=highlight_scope
axis_highlight=axis_highlight
legend=legend
tooltip=tooltip
charts_theme=charts_theme
highlighted_item=highlighted_item
on_highlight_change=on_highlight_change
on_item_click=on_item_click
on_axis_click=on_axis_click
on_legend_click=on_legend_click
loading_view=loading_view
empty_view=empty_view
embed_mode=embed_mode
overlay_mount=overlay_mount
chart_kind=chart_kind
>
{children.map(|c| c())}
</ResponsiveChartMeasuredHost>
}
}