use crate::blobs::EncodedBlob;
use crate::formatting::Formatting;
pub use crate::labels::Label;
use crate::query_data::{has_query_data, set_query_field, unset_query_field};
#[cfg(feature = "fp-bindgen")]
use fp_bindgen::prelude::Serializable;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use typed_builder::TypedBuilder;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Cell {
Checkbox(CheckboxCell),
Code(CodeCell),
Discussion(DiscussionCell),
Divider(DividerCell),
Graph(GraphCell),
Heading(HeadingCell),
Image(ImageCell),
ListItem(ListItemCell),
Log(LogCell),
Provider(ProviderCell),
Table(TableCell),
Timeline(TimelineCell),
Text(TextCell),
}
impl Cell {
pub fn content(&self) -> Option<&str> {
match self {
Cell::Checkbox(cell) => Some(&cell.content),
Cell::Code(cell) => Some(&cell.content),
Cell::Discussion(_) => None,
Cell::Divider(_) => None,
Cell::Graph(_) => None,
Cell::Heading(cell) => Some(&cell.content),
Cell::Image(_) => None,
Cell::ListItem(cell) => Some(&cell.content),
Cell::Log(_) => None,
Cell::Provider(_) => None,
Cell::Table(_) => None,
Cell::Text(cell) => Some(&cell.content),
Cell::Timeline(_) => None,
}
}
pub fn formatting(&self) -> Option<&Formatting> {
match self {
Cell::Code(_)
| Cell::Discussion(_)
| Cell::Divider(_)
| Cell::Graph(_)
| Cell::Image(_)
| Cell::Log(_)
| Cell::Provider(_)
| Cell::Table(_)
| Cell::Timeline(_) => None,
Cell::Checkbox(cell) => Some(&cell.formatting),
Cell::Heading(cell) => Some(&cell.formatting),
Cell::ListItem(cell) => Some(&cell.formatting),
Cell::Text(cell) => Some(&cell.formatting),
}
}
pub fn supports_formatting(&self) -> bool {
match self {
Cell::Code(_)
| Cell::Discussion(_)
| Cell::Divider(_)
| Cell::Graph(_)
| Cell::Image(_)
| Cell::Log(_)
| Cell::Table(_)
| Cell::Timeline(_) => false,
Cell::Checkbox(_)
| Cell::Heading(_)
| Cell::ListItem(_)
| Cell::Provider(_)
| Cell::Text(_) => true,
}
}
pub fn id(&self) -> &str {
match self {
Cell::Checkbox(cell) => &cell.id,
Cell::Code(cell) => &cell.id,
Cell::Discussion(cell) => &cell.id,
Cell::Divider(cell) => &cell.id,
Cell::Graph(cell) => &cell.id,
Cell::Heading(cell) => &cell.id,
Cell::Image(cell) => &cell.id,
Cell::ListItem(cell) => &cell.id,
Cell::Log(cell) => &cell.id,
Cell::Provider(cell) => &cell.id,
Cell::Table(cell) => &cell.id,
Cell::Text(cell) => &cell.id,
Cell::Timeline(cell) => &cell.id,
}
}
pub fn text(&self) -> Option<&str> {
self.content()
}
#[must_use]
pub fn with_id(&self, id: &str) -> Self {
match self {
Cell::Checkbox(cell) => Cell::Checkbox(CheckboxCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Code(cell) => Cell::Code(CodeCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Discussion(cell) => Cell::Discussion(DiscussionCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Divider(cell) => Cell::Divider(DividerCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Graph(cell) => Cell::Graph(GraphCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Heading(cell) => Cell::Heading(HeadingCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Image(cell) => Cell::Image(ImageCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::ListItem(cell) => Cell::ListItem(ListItemCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Log(cell) => Cell::Log(LogCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Provider(cell) => Cell::Provider(ProviderCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Table(cell) => Cell::Table(TableCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Text(cell) => Cell::Text(TextCell {
id: id.to_owned(),
..cell.clone()
}),
Cell::Timeline(cell) => Cell::Timeline(TimelineCell {
id: id.to_owned(),
..cell.clone()
}),
}
}
#[must_use]
pub fn with_text(&self, text: impl Into<String>) -> Self {
match self {
Cell::Checkbox(cell) => Cell::Checkbox(CheckboxCell {
id: cell.id.clone(),
content: text.into(),
formatting: Formatting::default(),
..*cell
}),
Cell::Code(cell) => Cell::Code(CodeCell {
id: cell.id.clone(),
content: text.into(),
syntax: cell.syntax.clone(),
..*cell
}),
Cell::Discussion(cell) => Cell::Discussion(cell.clone()),
Cell::Divider(cell) => Cell::Divider(cell.clone()),
Cell::Graph(cell) => Cell::Graph(cell.clone()),
Cell::Heading(cell) => Cell::Heading(HeadingCell {
id: cell.id.clone(),
content: text.into(),
formatting: Formatting::default(),
..*cell
}),
Cell::Image(cell) => Cell::Image(cell.clone()),
Cell::ListItem(cell) => Cell::ListItem(ListItemCell {
id: cell.id.clone(),
content: text.into(),
formatting: Formatting::default(),
..*cell
}),
Cell::Log(cell) => Cell::Log(cell.clone()),
Cell::Provider(cell) => Cell::Provider(cell.clone()),
Cell::Table(cell) => Cell::Table(cell.clone()),
Cell::Text(cell) => Cell::Text(TextCell {
id: cell.id.clone(),
content: text.into(),
formatting: Formatting::default(),
..*cell
}),
Cell::Timeline(cell) => Cell::Timeline(cell.clone()),
}
}
#[must_use]
pub fn with_rich_text(&self, text: impl Into<String>, formatting: Formatting) -> Self {
match self {
Cell::Checkbox(cell) => Cell::Checkbox(CheckboxCell {
id: cell.id.clone(),
content: text.into(),
formatting,
..*cell
}),
Cell::Heading(cell) => Cell::Heading(HeadingCell {
id: cell.id.clone(),
content: text.into(),
formatting,
..*cell
}),
Cell::ListItem(cell) => Cell::ListItem(ListItemCell {
id: cell.id.clone(),
content: text.into(),
formatting,
..*cell
}),
Cell::Text(cell) => Cell::Text(TextCell {
id: cell.id.clone(),
content: text.into(),
formatting,
..*cell
}),
Cell::Code(_)
| Cell::Discussion(_)
| Cell::Divider(_)
| Cell::Graph(_)
| Cell::Image(_)
| Cell::Log(_)
| Cell::Provider(_)
| Cell::Table(_)
| Cell::Timeline(_) => self.with_text(text),
}
}
#[must_use]
pub fn with_text_for_field<T>(
&self,
text: T,
formatting: Option<Formatting>,
field: Option<impl AsRef<str>>,
) -> Self
where
T: Into<String> + AsRef<str>,
{
match (self, field) {
(Cell::Provider(cell), Some(field)) => {
Cell::Provider(cell.with_query_field(field.as_ref(), text))
}
(cell, _) => {
if let Some(formatting) = formatting {
cell.with_rich_text(text, formatting)
} else {
cell.with_text(text)
}
}
}
}
pub fn id_mut(&mut self) -> &mut String {
match self {
Cell::Checkbox(cell) => &mut cell.id,
Cell::Code(cell) => &mut cell.id,
Cell::Discussion(cell) => &mut cell.id,
Cell::Divider(cell) => &mut cell.id,
Cell::Graph(cell) => &mut cell.id,
Cell::Heading(cell) => &mut cell.id,
Cell::Image(cell) => &mut cell.id,
Cell::ListItem(cell) => &mut cell.id,
Cell::Log(cell) => &mut cell.id,
Cell::Provider(cell) => &mut cell.id,
Cell::Table(cell) => &mut cell.id,
Cell::Text(cell) => &mut cell.id,
Cell::Timeline(cell) => &mut cell.id,
}
}
pub fn formatting_mut(&mut self) -> Option<&mut Formatting> {
match self {
Cell::Checkbox(cell) => Some(&mut cell.formatting),
Cell::Heading(cell) => Some(&mut cell.formatting),
Cell::ListItem(cell) => Some(&mut cell.formatting),
Cell::Text(cell) => Some(&mut cell.formatting),
Cell::Code(_)
| Cell::Discussion(_)
| Cell::Divider(_)
| Cell::Graph(_)
| Cell::Image(_)
| Cell::Log(_)
| Cell::Provider(_)
| Cell::Table(_)
| Cell::Timeline(_) => None,
}
}
pub fn text_mut(&mut self) -> Option<&mut String> {
match self {
Cell::Checkbox(cell) => Some(&mut cell.content),
Cell::Code(cell) => Some(&mut cell.content),
Cell::Discussion(_) => None,
Cell::Divider(_) => None,
Cell::Image(_) => None,
Cell::Graph(_) => None,
Cell::Heading(cell) => Some(&mut cell.content),
Cell::ListItem(cell) => Some(&mut cell.content),
Cell::Log(_) => None,
Cell::Provider(_) => None,
Cell::Table(_) => None,
Cell::Text(cell) => Some(&mut cell.content),
Cell::Timeline(_) => None,
}
}
pub fn type_str(&self) -> &str {
match self {
Cell::Checkbox(_) => "checkbox",
Cell::Code(_) => "code",
Cell::Discussion(_) => "discussion",
Cell::Divider(_) => "divider",
Cell::Graph(_) => "graph",
Cell::Heading(_) => "heading",
Cell::Image(_) => "image",
Cell::ListItem(_) => "list item",
Cell::Log(_) => "log",
Cell::Provider(cell) => &cell.intent,
Cell::Table(_) => "table",
Cell::Text(_) => "text",
Cell::Timeline(_) => "timeline",
}
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct CheckboxCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default)]
pub checked: bool,
#[builder(default, setter(into))]
pub content: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Formatting::is_empty")]
pub formatting: Formatting,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub level: Option<u8>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct CodeCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(into))]
pub content: String,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
#[builder(default, setter(into, strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub syntax: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct DividerCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct GraphCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub data_links: Vec<String>,
pub graph_type: GraphType,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
#[builder(default)]
pub stacking_type: StackingType,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct HeadingCell {
#[builder(default, setter(into))]
pub id: String,
pub heading_type: HeadingType,
#[builder(default, setter(into))]
pub content: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Formatting::is_empty")]
pub formatting: Formatting,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct LogCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub data_links: Vec<String>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub display_fields: Option<Vec<String>>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hide_similar_values: Option<bool>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub expanded_indices: Option<Vec<LogRecordIndex>>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub visibility_filter: Option<LogVisibilityFilter>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selected_indices: Option<Vec<LogRecordIndex>>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub highlighted_indices: Option<Vec<LogRecordIndex>>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum LogVisibilityFilter {
All,
Selected,
Highlighted,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct LogRecordIndex {
pub link_index: u8,
pub record_index: u32,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct ListItemCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(into))]
pub content: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Formatting::is_empty")]
pub formatting: Formatting,
#[builder(default)]
pub list_type: ListType,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub level: Option<u8>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub start_number: Option<u16>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct ProviderCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(into))]
pub intent: String,
#[builder(default, setter(into, strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub query_data: Option<String>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub response: Option<EncodedBlob>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output: Option<Vec<Cell>>,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
impl ProviderCell {
pub fn with_query_field(&self, field_name: impl AsRef<str>, value: impl AsRef<str>) -> Self {
let query_data = self.query_data.as_deref().unwrap_or_default();
let query_data = if value.as_ref().is_empty() {
unset_query_field(query_data, field_name)
} else {
set_query_field(query_data, field_name, value)
};
Self {
query_data: if has_query_data(&query_data) {
Some(query_data)
} else {
None
},
..self.clone()
}
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct TableCell {
#[builder(setter(into))]
pub id: String,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
#[builder(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub column_defs: Vec<TableColumnDefinition>,
#[builder(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub rows: Vec<TableRowData>,
}
pub type TableRowData = BTreeMap<String, TableCellValue>;
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct TableColumnDefinition {
pub key: String,
pub title: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum TableCellValue {
Empty,
Cell { cell: Cell },
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct TextCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(into))]
pub content: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Formatting::is_empty")]
pub formatting: Formatting,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[serde(rename_all = "camelCase")]
pub struct TimelineCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub data_links: Vec<String>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct ImageCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(into, strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub file_id: Option<String>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub progress: Option<f64>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub width: Option<i32>,
#[builder(default, setter(strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub height: Option<i32>,
#[builder(default, setter(into, strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
#[builder(default, setter(into, strip_option))]
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct DiscussionCell {
#[builder(default, setter(into))]
pub id: String,
#[builder(default, setter(into))]
pub thread_id: String,
#[builder(default, setter(strip_option))]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub read_only: Option<bool>,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum GraphType {
Bar,
Line,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum StackingType {
#[default]
None,
Stacked,
Percentage,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum HeadingType {
#[default]
H1,
H2,
H3,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[cfg_attr(
feature = "fp-bindgen",
derive(Serializable),
fp(rust_module = "fiberplane_models::notebooks")
)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum ListType {
Ordered,
#[default]
Unordered,
}