use serde::{Serialize, Serializer};
use super::data::MenuEntry;
macro_rules! string_enum {
($(#[$m:meta])* $name:ident { $($(#[$vm:meta])* $var:ident = $s:literal),* $(,)? }) => {
$(#[$m])*
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum $name {
$($(#[$vm])* $var,)*
Other(String),
}
impl $name {
pub fn as_str(&self) -> &str {
match self {
$(Self::$var => $s,)*
Self::Other(s) => s,
}
}
}
impl From<&str> for $name {
fn from(s: &str) -> Self {
match s {
$($s => Self::$var,)*
_ => Self::Other(s.to_owned()),
}
}
}
impl From<String> for $name {
fn from(s: String) -> Self {
Self::from(s.as_str())
}
}
impl ::std::fmt::Display for $name {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.write_str(self.as_str())
}
}
impl ::serde::Serialize for $name {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
};
}
pub(crate) use string_enum;
string_enum!(
Tone {
Neutral = "neutral",
Accent = "accent",
Info = "info",
Success = "success",
Warning = "warning",
Error = "error",
Pending = "pending",
Muted = "muted",
User = "user",
}
);
string_enum!(
Status {
Pending = "pending",
Running = "running",
Done = "done",
Error = "error",
Cancelled = "cancelled",
Ask = "ask",
}
);
string_enum!(
AgentStatus {
Pending = "pending",
Running = "running",
Done = "done",
Failed = "failed",
Aborted = "aborted",
Idle = "idle",
Parked = "parked",
}
);
string_enum!(
Mark {
Pick = "pick",
Drop = "drop",
}
);
string_enum!(
Gap {
None = "none",
Xs = "xs",
Sm = "sm",
Md = "md",
Lg = "lg",
}
);
string_enum!(
Align {
Start = "start",
Center = "center",
End = "end",
Baseline = "baseline",
Stretch = "stretch",
}
);
string_enum!(
Justify {
Between = "between",
End = "end",
}
);
string_enum!(
Wrap {
Word = "word",
Char = "char",
None = "none",
}
);
string_enum!(
Truncate {
End = "end",
Start = "start",
Middle = "middle",
}
);
string_enum!(
TextAlign {
Start = "start",
Center = "center",
End = "end",
}
);
string_enum!(
Fx {
Shimmer = "shimmer",
Pulse = "pulse",
None = "none",
}
);
string_enum!(
Token {
Muted = "muted",
Dim = "dim",
Strong = "strong",
Em = "em",
Accent = "accent",
Success = "success",
Warning = "warning",
Error = "error",
Info = "info",
Pending = "pending",
Code = "code",
Mono = "mono",
Path = "path",
Key = "key",
Link = "link",
Num = "num",
Ins = "ins",
Del = "del",
Mark = "mark",
Typo = "typo",
Icon = "icon",
Hide = "hide",
Title = "title",
}
);
string_enum!(
SpinnerStyle {
Braille = "braille",
Dots = "dots",
Starburst = "starburst",
Orbit = "orbit",
}
);
string_enum!(
ShimmerMode {
Classic = "classic",
Kitt = "kitt",
}
);
string_enum!(
ElapsedFormat {
Short = "short",
Clock = "clock",
}
);
string_enum!(
MeterStyle {
Bar = "bar",
Ring = "ring",
Blocks = "blocks",
}
);
string_enum!(
Size {
Sm = "sm",
Md = "md",
Lg = "lg",
}
);
string_enum!(
ChartKind {
Heatmap = "heatmap",
Bars = "bars",
Spark = "spark",
Line = "line",
Area = "area",
Donut = "donut",
}
);
string_enum!(
EffortLevel {
Off = "off",
Minimal = "minimal",
Low = "low",
Medium = "medium",
High = "high",
Xhigh = "xhigh",
Max = "max",
}
);
string_enum!(
DiffMode {
Unified = "unified",
Split = "split",
Auto = "auto",
}
);
string_enum!(
KvLayout {
Grid = "grid",
Inline = "inline",
}
);
string_enum!(
Measure {
Prose = "prose",
}
);
string_enum!(
CardVariant {
Bare = "bare",
}
);
string_enum!(
ButtonVariant {
Default = "default",
Primary = "primary",
Quiet = "quiet",
Danger = "danger",
}
);
string_enum!(
ButtonSize {
Sm = "sm",
Md = "md",
}
);
string_enum!(
TabsVariant {
Underline = "underline",
Segmented = "segmented",
}
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Disabled {
Flag(bool),
Reason(String),
}
impl Serialize for Disabled {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Flag(b) => s.serialize_bool(*b),
Self::Reason(r) => s.serialize_str(r),
}
}
}
impl From<bool> for Disabled {
fn from(b: bool) -> Self {
Self::Flag(b)
}
}
impl From<&str> for Disabled {
fn from(r: &str) -> Self {
Self::Reason(r.to_owned())
}
}
impl From<String> for Disabled {
fn from(r: String) -> Self {
Self::Reason(r)
}
}
string_enum!(
PickerSize {
Md = "md",
Lg = "lg",
Screen = "screen",
}
);
string_enum!(
PickerLayout {
Rows = "rows",
Cards = "cards",
Timeline = "timeline",
Tree = "tree",
}
);
string_enum!(
PickerPreview {
Side = "side",
Below = "below",
None = "none",
}
);
string_enum!(
PickerFocus {
List = "list",
Scopes = "scopes",
Tabs = "tabs",
Strip = "strip",
Preview = "preview",
}
);
string_enum!(
PickerState {
Ready = "ready",
Loading = "loading",
Error = "error",
}
);
string_enum!(
TargetKind {
Command = "command",
Path = "path",
Pattern = "pattern",
Query = "query",
Text = "text",
}
);
string_enum!(
ToolFrame {
Card = "card",
Inline = "inline",
}
);
string_enum!(
ChecklistMode {
Full = "full",
Hud = "hud",
Reminder = "reminder",
}
);
string_enum!(
ItemStatus {
Pending = "pending",
Active = "active",
Done = "done",
Dropped = "dropped",
Blocked = "blocked",
}
);
string_enum!(
OverlaySize {
Sm = "sm",
Md = "md",
Lg = "lg",
Full = "full",
}
);
string_enum!(
Side {
Right = "right",
}
);
string_enum!(
ColumnFormat {
Text = "text",
Num = "num",
Price = "price",
Bar = "bar",
Time = "time",
Elapsed = "elapsed",
Dim = "dim",
}
);
string_enum!(
ChoiceStyle {
Auto = "auto",
Segmented = "segmented",
Menu = "menu",
}
);
string_enum!(
InputType {
Checkbox = "checkbox",
Radio = "radio",
}
);
string_enum!(
InputVariant {
Well = "well",
Field = "field",
}
);
string_enum!(
OverlaySide {
Right = "right",
Left = "left",
Bottom = "bottom",
}
);
string_enum!(
OverlayVariant {
Edge = "edge",
Inset = "inset",
}
);
string_enum!(
RuleVariant {
Line = "line",
Note = "note",
Pin = "pin",
}
);
string_enum!(
CiteStyle {
Chip = "chip",
Pill = "pill",
Note = "note",
}
);
string_enum!(
SortDir {
Asc = "asc",
Desc = "desc",
}
);
string_enum!(
TableVariant {
Check = "check",
Bar = "bar",
}
);
string_enum!(
ToolConfirm {
Card = "card",
Strip = "strip",
Scopes = "scopes",
}
);
string_enum!(
Approved {
Once = "once",
Session = "session",
Always = "always",
Denied = "denied",
}
);
string_enum!(
SelectVariant {
Field = "field",
Quiet = "quiet",
}
);
string_enum!(
SwitchVariant {
Default = "default",
Compact = "compact",
Segment = "segment",
}
);
string_enum!(
SliderVariant {
Default = "default",
Accent = "accent",
}
);
string_enum!(
SliderFormat {
Number = "number",
Percent = "percent",
Duration = "duration",
}
);
string_enum!(
FieldVariant {
Stacked = "stacked",
Row = "row",
Grid = "grid",
}
);
string_enum!(
OtpVariant {
Cells = "cells",
Joined = "joined",
Underline = "underline",
}
);
string_enum!(
OtpState {
Error = "error",
Success = "success",
}
);
string_enum!(
ButtonsVariant {
Joined = "joined",
Split = "split",
Toolbar = "toolbar",
}
);
string_enum!(
AvatarVariant {
Circle = "circle",
Square = "square",
}
);
string_enum!(
AvatarSize {
Xs = "xs",
Sm = "sm",
Md = "md",
Lg = "lg",
}
);
string_enum!(
BreadcrumbVariant {
Chevron = "chevron",
Path = "path",
}
);
string_enum!(
PagerVariant {
Range = "range",
Pages = "pages",
More = "more",
}
);
string_enum!(
EmptyVariant {
Center = "center",
Inline = "inline",
Drop = "drop",
}
);
string_enum!(
SkeletonVariant {
Shimmer = "shimmer",
Pulse = "pulse",
Wire = "wire",
}
);
string_enum!(
SkeletonShape {
Text = "text",
Avatar = "avatar",
Rows = "rows",
Card = "card",
Block = "block",
}
);
string_enum!(
CalendarVariant {
Month = "month",
Week = "week",
}
);
string_enum!(
WeekStart {
Mon = "mon",
Sun = "sun",
}
);
string_enum!(
MenuVariant {
Default = "default",
Dense = "dense",
}
);
string_enum!(
MenuAlign {
Start = "start",
End = "end",
}
);
string_enum!(
MenubarVariant {
Strip = "strip",
Pill = "pill",
}
);
string_enum!(
NavVariant {
Pills = "pills",
Links = "links",
}
);
string_enum!(
SplitVariant {
Hairline = "hairline",
Gutter = "gutter",
Tiles = "tiles",
}
);
string_enum!(
SplitDir {
Row = "row",
Col = "col",
}
);
string_enum!(
ScrollVariant {
Bar = "bar",
Fade = "fade",
}
);
string_enum!(
Stick {
End = "end",
}
);
string_enum!(
ScrollBar {
Auto = "auto",
Always = "always",
}
);
string_enum!(
CarouselVariant {
Peek = "peek",
Arrows = "arrows",
Strip = "strip",
}
);
string_enum!(
MessageVariant {
Auto = "auto",
Bubble = "bubble",
Flat = "flat",
}
);
string_enum!(
MessageSide {
Start = "start",
End = "end",
}
);
string_enum!(
Reveal {
Hover = "hover",
Always = "always",
}
);
string_enum!(
AttachmentVariant {
Chip = "chip",
Tile = "tile",
Pill = "pill",
}
);
string_enum!(
AttachmentState {
Idle = "idle",
Uploading = "uploading",
Processing = "processing",
Error = "error",
Done = "done",
}
);
string_enum!(
TraceVariant {
Rail = "rail",
Summary = "summary",
Card = "card",
}
);
string_enum!(
StacktraceVariant {
Frames = "frames",
Split = "split",
Mono = "mono",
}
);
string_enum!(
SuggestionsVariant {
Chips = "chips",
Rows = "rows",
Cards = "cards",
}
);
string_enum!(
QuestionsVariant {
Steps = "steps",
Inline = "inline",
List = "list",
}
);
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)]
pub struct Span {
pub t: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub s: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fx: Option<Fx>,
#[serde(skip_serializing_if = "Option::is_none")]
pub href: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub cite: Vec<Cite>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)]
pub struct Cite {
pub href: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub n: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub site: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub snippet: Option<String>,
}
impl Cite {
pub fn new(href: impl Into<String>) -> Self {
Self { href: href.into(), ..Self::default() }
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub const fn n(mut self, n: u32) -> Self {
self.n = Some(n);
self
}
pub fn site(mut self, site: impl Into<String>) -> Self {
self.site = Some(site.into());
self
}
pub fn snippet(mut self, snippet: impl Into<String>) -> Self {
self.snippet = Some(snippet.into());
self
}
}
impl Span {
pub fn new(t: impl Into<String>) -> Self {
Self { t: t.into(), ..Self::default() }
}
pub fn style(mut self, token: impl Into<Token>) -> Self {
let token = token.into();
self.s = Some(match self.s.take() {
Some(s) if !s.is_empty() => format!("{s} {token}"),
_ => token.to_string(),
});
self
}
pub fn fx(mut self, fx: impl Into<Fx>) -> Self {
self.fx = Some(fx.into());
self
}
pub fn href(mut self, href: impl Into<String>) -> Self {
self.href = Some(href.into());
self
}
pub fn cite(mut self, cite: Cite) -> Self {
self.cite.push(cite);
self
}
}
impl From<&str> for Span {
fn from(t: &str) -> Self {
Self::new(t)
}
}
impl From<String> for Span {
fn from(t: String) -> Self {
Self::new(t)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Text {
Plain(String),
Spans(Vec<Span>),
}
impl Text {
pub fn plain(&self) -> String {
match self {
Self::Plain(s) => s.clone(),
Self::Spans(spans) => spans.iter().map(|s| s.t.as_str()).collect(),
}
}
}
impl Default for Text {
fn default() -> Self {
Self::Plain(String::new())
}
}
impl Serialize for Text {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Plain(t) => s.serialize_str(t),
Self::Spans(spans) => spans.serialize(s),
}
}
}
impl From<&str> for Text {
fn from(t: &str) -> Self {
Self::Plain(t.to_owned())
}
}
impl From<String> for Text {
fn from(t: String) -> Self {
Self::Plain(t)
}
}
impl From<&String> for Text {
fn from(t: &String) -> Self {
Self::Plain(t.clone())
}
}
impl From<Span> for Text {
fn from(span: Span) -> Self {
Self::Spans(vec![span])
}
}
impl From<Vec<Span>> for Text {
fn from(spans: Vec<Span>) -> Self {
Self::Spans(spans)
}
}
impl<const N: usize> From<[Span; N]> for Text {
fn from(spans: [Span; N]) -> Self {
Self::Spans(spans.into())
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Extent {
Ch(f64),
Lines(f64),
Fraction(f64),
}
impl Serialize for Extent {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match *self {
Self::Ch(n) => s.collect_str(&format_args!("{n}ch")),
Self::Lines(n) => s.collect_str(&format_args!("{n}lines")),
Self::Fraction(f) => s.serialize_f64(f),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize)]
pub struct Bound {
#[serde(skip_serializing_if = "Option::is_none")]
pub w: Option<Extent>,
#[serde(skip_serializing_if = "Option::is_none")]
pub h: Option<Extent>,
}
impl Bound {
pub const fn w(w: Extent) -> Self {
Self { w: Some(w), h: None }
}
pub const fn h(h: Extent) -> Self {
Self { w: None, h: Some(h) }
}
pub const fn wh(w: Extent, h: Extent) -> Self {
Self { w: Some(w), h: Some(h) }
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Basis {
Fraction(f64),
Content,
}
impl Serialize for Basis {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match *self {
Self::Fraction(f) => s.serialize_f64(f),
Self::Content => s.serialize_str("content"),
}
}
}
impl From<f64> for Basis {
fn from(f: f64) -> Self {
Self::Fraction(f)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Height {
Px(f64),
Ch(f64),
Lines(f64),
}
impl Serialize for Height {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match *self {
Self::Px(px) => s.serialize_f64(px),
Self::Ch(n) => s.collect_str(&format_args!("{n}ch")),
Self::Lines(n) => s.collect_str(&format_args!("{n}lines")),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum PaneMin {
All(Extent),
Each(Vec<Option<Extent>>),
Bound(Bound),
}
impl Serialize for PaneMin {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::All(extent) => extent.serialize(s),
Self::Each(extents) => extents.serialize(s),
Self::Bound(bound) => bound.serialize(s),
}
}
}
impl From<Extent> for PaneMin {
fn from(extent: Extent) -> Self {
Self::All(extent)
}
}
impl From<Vec<Option<Extent>>> for PaneMin {
fn from(extents: Vec<Option<Extent>>) -> Self {
Self::Each(extents)
}
}
impl From<Bound> for PaneMin {
fn from(bound: Bound) -> Self {
Self::Bound(bound)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TextFlag {
Flag(bool),
Text(Text),
}
impl Serialize for TextFlag {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Flag(b) => s.serialize_bool(*b),
Self::Text(t) => t.serialize(s),
}
}
}
impl From<bool> for TextFlag {
fn from(b: bool) -> Self {
Self::Flag(b)
}
}
impl<T: Into<Text>> From<T> for TextFlag {
fn from(t: T) -> Self {
Self::Text(t.into())
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SliderValue {
One(f64),
Range(f64, f64),
}
impl Serialize for SliderValue {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match *self {
Self::One(v) => s.serialize_f64(v),
Self::Range(lo, hi) => [lo, hi].serialize(s),
}
}
}
impl From<f64> for SliderValue {
fn from(v: f64) -> Self {
Self::One(v)
}
}
impl From<(f64, f64)> for SliderValue {
fn from((lo, hi): (f64, f64)) -> Self {
Self::Range(lo, hi)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Ticks {
Steps(bool),
Parts(u32),
At(Vec<f64>),
}
impl Serialize for Ticks {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Steps(b) => s.serialize_bool(*b),
Self::Parts(n) => s.serialize_u32(*n),
Self::At(values) => values.serialize(s),
}
}
}
impl From<bool> for Ticks {
fn from(b: bool) -> Self {
Self::Steps(b)
}
}
impl From<u32> for Ticks {
fn from(n: u32) -> Self {
Self::Parts(n)
}
}
impl From<Vec<f64>> for Ticks {
fn from(values: Vec<f64>) -> Self {
Self::At(values)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum OtpMask {
Dots(bool),
Char(String),
}
impl Serialize for OtpMask {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Dots(b) => s.serialize_bool(*b),
Self::Char(c) => s.serialize_str(c),
}
}
}
impl From<bool> for OtpMask {
fn from(b: bool) -> Self {
Self::Dots(b)
}
}
impl From<&str> for OtpMask {
fn from(c: &str) -> Self {
Self::Char(c.to_owned())
}
}
impl From<char> for OtpMask {
fn from(c: char) -> Self {
Self::Char(c.to_string())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Noun {
Word(String),
Forms(String, String),
}
impl Serialize for Noun {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Word(w) => s.serialize_str(w),
Self::Forms(one, many) => [one, many].serialize(s),
}
}
}
impl From<&str> for Noun {
fn from(w: &str) -> Self {
Self::Word(w.to_owned())
}
}
impl From<String> for Noun {
fn from(w: String) -> Self {
Self::Word(w)
}
}
impl From<(&str, &str)> for Noun {
fn from((one, many): (&str, &str)) -> Self {
Self::Forms(one.to_owned(), many.to_owned())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DateValue {
Day(String),
Range(String, Option<String>),
}
impl Serialize for DateValue {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Day(day) => s.serialize_str(day),
Self::Range(from, to) => (from, to).serialize(s),
}
}
}
impl From<&str> for DateValue {
fn from(day: &str) -> Self {
Self::Day(day.to_owned())
}
}
impl From<String> for DateValue {
fn from(day: String) -> Self {
Self::Day(day)
}
}
impl From<(&str, &str)> for DateValue {
fn from((from, to): (&str, &str)) -> Self {
Self::Range(from.to_owned(), Some(to.to_owned()))
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum NodeKey {
Str(String),
Int(i64),
}
impl Serialize for NodeKey {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Str(k) => s.serialize_str(k),
Self::Int(n) => s.serialize_i64(*n),
}
}
}
impl From<&str> for NodeKey {
fn from(k: &str) -> Self {
Self::Str(k.to_owned())
}
}
impl From<String> for NodeKey {
fn from(k: String) -> Self {
Self::Str(k)
}
}
impl From<&String> for NodeKey {
fn from(k: &String) -> Self {
Self::Str(k.clone())
}
}
macro_rules! int_key {
($($t:ty),*) => {
$(impl From<$t> for NodeKey {
fn from(n: $t) -> Self {
Self::Int(n as i64)
}
})*
};
}
int_key!(i32, i64, u32, u64, usize);
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)]
pub struct Actions {
#[serde(skip_serializing_if = "Option::is_none")]
pub click: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dblclick: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub menu: Vec<MenuEntry>,
}
impl Actions {
pub fn new() -> Self {
Self::default()
}
pub fn click(mut self, act: impl Into<String>) -> Self {
self.click = Some(act.into());
self
}
pub fn dblclick(mut self, act: impl Into<String>) -> Self {
self.dblclick = Some(act.into());
self
}
pub fn menu(mut self, entry: impl Into<MenuEntry>) -> Self {
self.menu.push(entry.into());
self
}
}