diff --git a/dev_plugin/src/inline-view.tsx b/dev_plugin/src/inline-view.tsx
index cfe0413..f8b4e22 100644
--- a/dev_plugin/src/inline-view.tsx
+++ b/dev_plugin/src/inline-view.tsx
@@ -1,4 +1,4 @@
-import { Content, Inline } from "@project-gauntlet/api/components";
+import { Content, Icons, Inline } from "@project-gauntlet/api/components";
import { ReactNode } from "react";
export default function InlineView(props: { text: string }): ReactNode | undefined {
@@ -15,6 +15,12 @@ export default function InlineView(props: { text: string }): ReactNode | undefin
+
+
+ Testing inline view center
+
+
+
Testing inline view right
diff --git a/js/api/src/gen/components.tsx b/js/api/src/gen/components.tsx
index c6aa56d..e641339 100644
--- a/js/api/src/gen/components.tsx
+++ b/js/api/src/gen/components.tsx
@@ -110,7 +110,9 @@ declare global {
["gauntlet:form"]: {
children?: ElementComponent;
};
- ["gauntlet:inline_separator"]: {};
+ ["gauntlet:inline_separator"]: {
+ icon?: Icons;
+ };
["gauntlet:inline"]: {
children?: ElementComponent;
};
@@ -597,8 +599,11 @@ Form.Checkbox = Checkbox;
Form.DatePicker = DatePicker;
Form.Select = Select;
Form.Separator = Separator;
-export const InlineSeparator: FC = (): ReactNode => {
- return ;
+export interface InlineSeparatorProps {
+ icon?: Icons;
+}
+export const InlineSeparator: FC = (props: InlineSeparatorProps): ReactNode => {
+ return ;
};
export interface InlineProps {
children?: ElementComponent;
diff --git a/rust/client/src/ui/mod.rs b/rust/client/src/ui/mod.rs
index 565a870..093aa7d 100644
--- a/rust/client/src/ui/mod.rs
+++ b/rust/client/src/ui/mod.rs
@@ -707,7 +707,8 @@ impl AppModel {
Command::batch([
reposition(window::Id::MAIN, Position::Centered, Size::new(WINDOW_WIDTH, WINDOW_HEIGHT)),
- window::resize(window::Id::MAIN, Size::new(WINDOW_WIDTH, WINDOW_HEIGHT))
+ window::resize(window::Id::MAIN, Size::new(WINDOW_WIDTH, WINDOW_HEIGHT)),
+ focus(self.search_field_id.clone()),
])
}
Some(PluginViewData { top_level_view: false, plugin_id, entrypoint_id, .. }) => {
diff --git a/rust/client/src/ui/widget.rs b/rust/client/src/ui/widget.rs
index 9708574..31f8950 100644
--- a/rust/client/src/ui/widget.rs
+++ b/rust/client/src/ui/widget.rs
@@ -4,7 +4,7 @@ use std::str::FromStr;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use anyhow::anyhow;
-use iced::{Font, Length, Padding};
+use iced::{Alignment, color, Font, Length, Padding};
use iced::alignment::Horizontal;
use iced::font::Weight;
use iced::widget::{button, checkbox, column, container, horizontal_rule, horizontal_space, image, pick_list, row, scrollable, Space, text, text_input, tooltip, vertical_rule, vertical_space};
@@ -118,6 +118,8 @@ pub enum ComponentRenderContext {
H4,
H5,
H6,
+ Inline,
+ GridItem,
List {
widget_id: NativeUiWidgetId
},
@@ -136,6 +138,12 @@ pub enum ComponentRenderContext {
}
}
+impl ComponentRenderContext {
+ fn is_content_centered(&self) -> bool {
+ matches!(self, ComponentRenderContext::Inline | ComponentRenderContext::GridItem)
+ }
+}
+
impl ComponentWidgetWrapper {
pub fn widget(
id: NativeUiWidgetId,
@@ -431,12 +439,19 @@ impl ComponentWidgetWrapper {
.into()
}
ComponentWidget::Paragraph { children } => {
- let paragraph: Element<_> = render_children_string(children, context);
+ let centered = context.is_content_centered();
- container(paragraph)
+ let paragraph: Element<_> = render_children_string(children, ComponentRenderContext::None);
+
+ let mut content = container(paragraph)
.width(Length::Fill)
- .padding(Padding::new(5.0))
- .into()
+ .padding(Padding::new(5.0));
+
+ if centered {
+ content = content.center_x()
+ }
+
+ content.into()
}
// ComponentWidget::Link { children, href } => {
// let content: Element<_> = render_children_string(children, ComponentRenderContext::None);
@@ -458,8 +473,19 @@ impl ComponentWidgetWrapper {
// }
// }
ComponentWidget::Image { source } => {
- image(Handle::from_memory(source.data.clone())) // FIXME really expensive clone
- .into()
+ let centered = context.is_content_centered();
+
+ let content: Element<_> = image(Handle::from_memory(source.data.clone())) // FIXME really expensive clone
+ .into();
+
+ let mut content = container(content)
+ .width(Length::Fill);
+
+ if centered {
+ content = content.center_x()
+ }
+
+ content.into()
}
ComponentWidget::H1 { children } => {
render_children_string(children, ComponentRenderContext::H1)
@@ -509,8 +535,21 @@ impl ComponentWidgetWrapper {
// .into()
// }
ComponentWidget::Content { children } => {
- column(render_children(children, ComponentRenderContext::None))
- .into()
+ let centered = context.is_content_centered();
+
+ let content: Element<_> = column(render_children(children, context))
+ .into();
+
+ if centered {
+ container(content)
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .center_x()
+ .center_y()
+ .into()
+ } else {
+ content
+ }
}
ComponentWidget::Detail { children } => {
let ComponentWidgetState::Detail { show_action_panel } = *state else {
@@ -745,47 +784,66 @@ impl ComponentWidgetWrapper {
render_root(show_action_panel, widget_id, children, content, context)
}
- ComponentWidget::InlineSeparator => {
- vertical_rule(1)
- .into()
+ ComponentWidget::InlineSeparator { icon } => {
+ match icon {
+ None => vertical_rule(1).into(),
+ Some(icon) => {
+ let top_rule: Element<_> = vertical_rule(1)
+ .into();
+
+ let top_rule = container(top_rule)
+ .center_x()
+ .into();
+
+ let icon = text(icon_to_bootstrap(icon))
+ .font(icons::BOOTSTRAP_FONT)
+ .size(30)
+ .into();
+
+ let bot_rule: Element<_> = vertical_rule(1)
+ .into();
+
+ let bot_rule = container(bot_rule)
+ .center_x()
+ .into();
+
+ column([top_rule, icon, bot_rule])
+ .align_items(Alignment::Center)
+ .into()
+ }
+ }
}
ComponentWidget::Inline { children } => {
- let contents: Vec<_> = render_children_by_type(children, |widget| matches!(widget, ComponentWidget::Content { .. }), ComponentRenderContext::None)
+ let content: Vec> = children
.into_iter()
- .map(|content_element| {
- container(content_element)
- .width(Length::FillPortion(3))
- // .padding(Padding::from([5.0, 5.0, 0.0, 5.0]))
- .into()
+ .map(|child| {
+ let (widget, _) = &*child.get();
+
+ match widget {
+ ComponentWidget::InlineSeparator { .. } => {
+ child.render_widget(ComponentRenderContext::None)
+ }
+ ComponentWidget::Content { .. } => {
+ let element = child.render_widget(ComponentRenderContext::Inline);
+
+ container(element)
+ .width(Length::Fill)
+ .into()
+ }
+ _ => panic!("unexpected widget kind {:?}", widget)
+ }
})
.collect();
- // let mut separators: Vec<_> = render_children_by_type(children, |widget| matches!(widget, ComponentWidget::InlineSeparator { .. }), ComponentRenderContext::None);
-
- // let mut left = contents.len();
-
- let contents: Vec<_> = contents.into_iter()
- .flat_map(|i| {
- // if left > 1 {
- // left = left - 1;
- // if separators.is_empty() {
- // let separator = vertical_rule(1).into();
- // vec![i, separator]
- // } else {
- // let separator = separators.remove(0);
- // vec![i, separator]
- // }
- // } else {
- vec![i]
- // }
- })
- .collect();
-
- let content: Element<_> = row(contents)
+ let content: Element<_> = row(content)
.into();
container(content)
.padding(Padding::new(5.0))
+ .center_x()
+ .center_y()
+ .height(100)
+ .max_height(100)
.into()
}
ComponentWidget::EmptyView { title, description, image } => {
@@ -922,7 +980,7 @@ impl ComponentWidgetWrapper {
panic!("not supposed to be passed to grid item: {:?}", context)
};
- let content: Element<_> = column(render_children(children, ComponentRenderContext::None))
+ let content: Element<_> = column(render_children(children, ComponentRenderContext::GridItem))
.into();
let title: Element<_> = text(title)
@@ -1211,6 +1269,8 @@ fn render_text_part<'a>(value: &str, context: ComponentRenderContext) -> Element
ComponentRenderContext::Root { .. } => panic!("not supposed to be passed to text part"),
ComponentRenderContext::ActionPanel { .. } => panic!("not supposed to be passed to text part"),
ComponentRenderContext::Action { .. } => panic!("not supposed to be passed to text part"),
+ ComponentRenderContext::Inline => panic!("not supposed to be passed to text part"),
+ ComponentRenderContext::GridItem => panic!("not supposed to be passed to text part")
};
let mut text = text(value);
diff --git a/rust/component_model/src/lib.rs b/rust/component_model/src/lib.rs
index 8e65c3f..d1a9150 100644
--- a/rust/component_model/src/lib.rs
+++ b/rust/component_model/src/lib.rs
@@ -833,7 +833,9 @@ pub fn create_component_model() -> Vec {
let inline_separator_component = component(
"inline_separator",
"InlineSeparator",
- [],
+ [
+ property("icon", true, PropertyType::Enum { name: "Icons".to_owned() }),
+ ],
children_none(),
);