diff --git a/ui/components/src/ui/components/tailwind/form/Inputs.scala b/ui/components/src/ui/components/tailwind/form/Inputs.scala new file mode 100644 index 0000000..ce8d7d2 --- /dev/null +++ b/ui/components/src/ui/components/tailwind/form/Inputs.scala @@ -0,0 +1,26 @@ +package works.iterative +package ui.components.tailwind.form + +import com.raquo.laminar.api.L.{textArea => ta, *, given} +import works.iterative.ui.components.tailwind.HtmlComponent +import com.raquo.laminar.nodes.ReactiveHtmlElement +import works.iterative.ui.model.Paragraph +import works.iterative.ui.model.FormItem +import org.scalajs.dom.html + +object Inputs: + + def textArea( + updates: Observer[Option[Paragraph]] + ): HtmlComponent[html.TextArea, FormItem[Paragraph]] = + (i: FormItem[Paragraph]) => + ta( + idAttr := i.id, + name := i.id, + rows := 5, + cls := "max-w-lg shadow-sm block w-full focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border border-gray-300 rounded-md", + value(i.value.toString), + onInput.mapToValue.setAsValue --> updates.contramap((v: String) => + Option(v).map(_.trim).filter(_.nonEmpty).map(Paragraph(_)) + ) + ) diff --git a/ui/components/src/ui/components/tailwind/form/Inputs.scala b/ui/components/src/ui/components/tailwind/form/Inputs.scala new file mode 100644 index 0000000..ce8d7d2 --- /dev/null +++ b/ui/components/src/ui/components/tailwind/form/Inputs.scala @@ -0,0 +1,26 @@ +package works.iterative +package ui.components.tailwind.form + +import com.raquo.laminar.api.L.{textArea => ta, *, given} +import works.iterative.ui.components.tailwind.HtmlComponent +import com.raquo.laminar.nodes.ReactiveHtmlElement +import works.iterative.ui.model.Paragraph +import works.iterative.ui.model.FormItem +import org.scalajs.dom.html + +object Inputs: + + def textArea( + updates: Observer[Option[Paragraph]] + ): HtmlComponent[html.TextArea, FormItem[Paragraph]] = + (i: FormItem[Paragraph]) => + ta( + idAttr := i.id, + name := i.id, + rows := 5, + cls := "max-w-lg shadow-sm block w-full focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border border-gray-300 rounded-md", + value(i.value.toString), + onInput.mapToValue.setAsValue --> updates.contramap((v: String) => + Option(v).map(_.trim).filter(_.nonEmpty).map(Paragraph(_)) + ) + ) diff --git a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala index 456edb0..40e4728 100644 --- a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala +++ b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala @@ -24,7 +24,7 @@ else "" ), prop.icon.map(_.element), - prop.text + prop.text.toString ) val rightProp: HtmlComponent[org.scalajs.dom.html.Div, ItemProp] = @@ -32,7 +32,7 @@ div( cls("mt-2 flex items-center text-sm text-gray-500 sm:mt-0"), prop.icon.map(_.element), - prop.text + prop.text.toString ) given HtmlComponent[Paragraph, Label] = @@ -69,7 +69,7 @@ cls := "flex items-center justify-between", p( cls := "text-sm font-medium text-indigo-600 truncate", - i.title + i.title.toString ), div( cls := "ml-2 flex-shrink-0 flex", @@ -105,7 +105,7 @@ cls( "z-10 sticky top-0 border-t border-b border-gray-200 bg-gray-50 px-6 py-1 text-sm font-medium text-gray-500" ), - i.title + i.title.toString ), ul( role := "list", diff --git a/ui/components/src/ui/components/tailwind/form/Inputs.scala b/ui/components/src/ui/components/tailwind/form/Inputs.scala new file mode 100644 index 0000000..ce8d7d2 --- /dev/null +++ b/ui/components/src/ui/components/tailwind/form/Inputs.scala @@ -0,0 +1,26 @@ +package works.iterative +package ui.components.tailwind.form + +import com.raquo.laminar.api.L.{textArea => ta, *, given} +import works.iterative.ui.components.tailwind.HtmlComponent +import com.raquo.laminar.nodes.ReactiveHtmlElement +import works.iterative.ui.model.Paragraph +import works.iterative.ui.model.FormItem +import org.scalajs.dom.html + +object Inputs: + + def textArea( + updates: Observer[Option[Paragraph]] + ): HtmlComponent[html.TextArea, FormItem[Paragraph]] = + (i: FormItem[Paragraph]) => + ta( + idAttr := i.id, + name := i.id, + rows := 5, + cls := "max-w-lg shadow-sm block w-full focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border border-gray-300 rounded-md", + value(i.value.toString), + onInput.mapToValue.setAsValue --> updates.contramap((v: String) => + Option(v).map(_.trim).filter(_.nonEmpty).map(Paragraph(_)) + ) + ) diff --git a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala index 456edb0..40e4728 100644 --- a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala +++ b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala @@ -24,7 +24,7 @@ else "" ), prop.icon.map(_.element), - prop.text + prop.text.toString ) val rightProp: HtmlComponent[org.scalajs.dom.html.Div, ItemProp] = @@ -32,7 +32,7 @@ div( cls("mt-2 flex items-center text-sm text-gray-500 sm:mt-0"), prop.icon.map(_.element), - prop.text + prop.text.toString ) given HtmlComponent[Paragraph, Label] = @@ -69,7 +69,7 @@ cls := "flex items-center justify-between", p( cls := "text-sm font-medium text-indigo-600 truncate", - i.title + i.title.toString ), div( cls := "ml-2 flex-shrink-0 flex", @@ -105,7 +105,7 @@ cls( "z-10 sticky top-0 border-t border-b border-gray-200 bg-gray-50 px-6 py-1 text-sm font-medium text-gray-500" ), - i.title + i.title.toString ), ul( role := "list", diff --git a/ui/model/src/Form.scala b/ui/model/src/Form.scala new file mode 100644 index 0000000..d9a978f --- /dev/null +++ b/ui/model/src/Form.scala @@ -0,0 +1,17 @@ +package works.iterative +package ui.model + +case class FormItem[Value]( + id: String, + label: OneLine, + description: Option[Paragraph], + value: Value +) + +case class FormSection( + header: OneLine, + description: Option[Paragraph], + items: List[FormItem[_]] +) + +case class Form(sections: List[FormSection]) diff --git a/ui/components/src/ui/components/tailwind/form/Inputs.scala b/ui/components/src/ui/components/tailwind/form/Inputs.scala new file mode 100644 index 0000000..ce8d7d2 --- /dev/null +++ b/ui/components/src/ui/components/tailwind/form/Inputs.scala @@ -0,0 +1,26 @@ +package works.iterative +package ui.components.tailwind.form + +import com.raquo.laminar.api.L.{textArea => ta, *, given} +import works.iterative.ui.components.tailwind.HtmlComponent +import com.raquo.laminar.nodes.ReactiveHtmlElement +import works.iterative.ui.model.Paragraph +import works.iterative.ui.model.FormItem +import org.scalajs.dom.html + +object Inputs: + + def textArea( + updates: Observer[Option[Paragraph]] + ): HtmlComponent[html.TextArea, FormItem[Paragraph]] = + (i: FormItem[Paragraph]) => + ta( + idAttr := i.id, + name := i.id, + rows := 5, + cls := "max-w-lg shadow-sm block w-full focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border border-gray-300 rounded-md", + value(i.value.toString), + onInput.mapToValue.setAsValue --> updates.contramap((v: String) => + Option(v).map(_.trim).filter(_.nonEmpty).map(Paragraph(_)) + ) + ) diff --git a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala index 456edb0..40e4728 100644 --- a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala +++ b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala @@ -24,7 +24,7 @@ else "" ), prop.icon.map(_.element), - prop.text + prop.text.toString ) val rightProp: HtmlComponent[org.scalajs.dom.html.Div, ItemProp] = @@ -32,7 +32,7 @@ div( cls("mt-2 flex items-center text-sm text-gray-500 sm:mt-0"), prop.icon.map(_.element), - prop.text + prop.text.toString ) given HtmlComponent[Paragraph, Label] = @@ -69,7 +69,7 @@ cls := "flex items-center justify-between", p( cls := "text-sm font-medium text-indigo-600 truncate", - i.title + i.title.toString ), div( cls := "ml-2 flex-shrink-0 flex", @@ -105,7 +105,7 @@ cls( "z-10 sticky top-0 border-t border-b border-gray-200 bg-gray-50 px-6 py-1 text-sm font-medium text-gray-500" ), - i.title + i.title.toString ), ul( role := "list", diff --git a/ui/model/src/Form.scala b/ui/model/src/Form.scala new file mode 100644 index 0000000..d9a978f --- /dev/null +++ b/ui/model/src/Form.scala @@ -0,0 +1,17 @@ +package works.iterative +package ui.model + +case class FormItem[Value]( + id: String, + label: OneLine, + description: Option[Paragraph], + value: Value +) + +case class FormSection( + header: OneLine, + description: Option[Paragraph], + items: List[FormItem[_]] +) + +case class Form(sections: List[FormSection]) diff --git a/ui/model/src/ItemList.scala b/ui/model/src/ItemList.scala index 7c56254..3aa7815 100644 --- a/ui/model/src/ItemList.scala +++ b/ui/model/src/ItemList.scala @@ -5,17 +5,17 @@ ) case class ItemProp( - text: String, + text: OneLine, icon: Option[Icon] = None ) case class ListSection( - title: String, + title: OneLine, items: List[ListItem] ) case class ListItem( - title: String, + title: OneLine, href: String, label: Option[Label] = None, leftProps: List[ItemProp] = Nil, diff --git a/ui/components/src/ui/components/tailwind/form/Inputs.scala b/ui/components/src/ui/components/tailwind/form/Inputs.scala new file mode 100644 index 0000000..ce8d7d2 --- /dev/null +++ b/ui/components/src/ui/components/tailwind/form/Inputs.scala @@ -0,0 +1,26 @@ +package works.iterative +package ui.components.tailwind.form + +import com.raquo.laminar.api.L.{textArea => ta, *, given} +import works.iterative.ui.components.tailwind.HtmlComponent +import com.raquo.laminar.nodes.ReactiveHtmlElement +import works.iterative.ui.model.Paragraph +import works.iterative.ui.model.FormItem +import org.scalajs.dom.html + +object Inputs: + + def textArea( + updates: Observer[Option[Paragraph]] + ): HtmlComponent[html.TextArea, FormItem[Paragraph]] = + (i: FormItem[Paragraph]) => + ta( + idAttr := i.id, + name := i.id, + rows := 5, + cls := "max-w-lg shadow-sm block w-full focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border border-gray-300 rounded-md", + value(i.value.toString), + onInput.mapToValue.setAsValue --> updates.contramap((v: String) => + Option(v).map(_.trim).filter(_.nonEmpty).map(Paragraph(_)) + ) + ) diff --git a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala index 456edb0..40e4728 100644 --- a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala +++ b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala @@ -24,7 +24,7 @@ else "" ), prop.icon.map(_.element), - prop.text + prop.text.toString ) val rightProp: HtmlComponent[org.scalajs.dom.html.Div, ItemProp] = @@ -32,7 +32,7 @@ div( cls("mt-2 flex items-center text-sm text-gray-500 sm:mt-0"), prop.icon.map(_.element), - prop.text + prop.text.toString ) given HtmlComponent[Paragraph, Label] = @@ -69,7 +69,7 @@ cls := "flex items-center justify-between", p( cls := "text-sm font-medium text-indigo-600 truncate", - i.title + i.title.toString ), div( cls := "ml-2 flex-shrink-0 flex", @@ -105,7 +105,7 @@ cls( "z-10 sticky top-0 border-t border-b border-gray-200 bg-gray-50 px-6 py-1 text-sm font-medium text-gray-500" ), - i.title + i.title.toString ), ul( role := "list", diff --git a/ui/model/src/Form.scala b/ui/model/src/Form.scala new file mode 100644 index 0000000..d9a978f --- /dev/null +++ b/ui/model/src/Form.scala @@ -0,0 +1,17 @@ +package works.iterative +package ui.model + +case class FormItem[Value]( + id: String, + label: OneLine, + description: Option[Paragraph], + value: Value +) + +case class FormSection( + header: OneLine, + description: Option[Paragraph], + items: List[FormItem[_]] +) + +case class Form(sections: List[FormSection]) diff --git a/ui/model/src/ItemList.scala b/ui/model/src/ItemList.scala index 7c56254..3aa7815 100644 --- a/ui/model/src/ItemList.scala +++ b/ui/model/src/ItemList.scala @@ -5,17 +5,17 @@ ) case class ItemProp( - text: String, + text: OneLine, icon: Option[Icon] = None ) case class ListSection( - title: String, + title: OneLine, items: List[ListItem] ) case class ListItem( - title: String, + title: OneLine, href: String, label: Option[Label] = None, leftProps: List[ItemProp] = Nil, diff --git a/ui/model/src/Label.scala b/ui/model/src/Label.scala index 19741fd..6d6f13f 100644 --- a/ui/model/src/Label.scala +++ b/ui/model/src/Label.scala @@ -1,3 +1,5 @@ package works.iterative.ui.model +// TODO: Rename to Tag? Metals does not like Label for some reason, never imports it as code action +// A conflict with something in Laminar case class Label(color: HighlightColor, text: String) diff --git a/ui/components/src/ui/components/tailwind/form/Inputs.scala b/ui/components/src/ui/components/tailwind/form/Inputs.scala new file mode 100644 index 0000000..ce8d7d2 --- /dev/null +++ b/ui/components/src/ui/components/tailwind/form/Inputs.scala @@ -0,0 +1,26 @@ +package works.iterative +package ui.components.tailwind.form + +import com.raquo.laminar.api.L.{textArea => ta, *, given} +import works.iterative.ui.components.tailwind.HtmlComponent +import com.raquo.laminar.nodes.ReactiveHtmlElement +import works.iterative.ui.model.Paragraph +import works.iterative.ui.model.FormItem +import org.scalajs.dom.html + +object Inputs: + + def textArea( + updates: Observer[Option[Paragraph]] + ): HtmlComponent[html.TextArea, FormItem[Paragraph]] = + (i: FormItem[Paragraph]) => + ta( + idAttr := i.id, + name := i.id, + rows := 5, + cls := "max-w-lg shadow-sm block w-full focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border border-gray-300 rounded-md", + value(i.value.toString), + onInput.mapToValue.setAsValue --> updates.contramap((v: String) => + Option(v).map(_.trim).filter(_.nonEmpty).map(Paragraph(_)) + ) + ) diff --git a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala index 456edb0..40e4728 100644 --- a/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala +++ b/ui/components/src/ui/components/tailwind/lists/stacked_lists/WithRightJustifiedSecondColumn.scala @@ -24,7 +24,7 @@ else "" ), prop.icon.map(_.element), - prop.text + prop.text.toString ) val rightProp: HtmlComponent[org.scalajs.dom.html.Div, ItemProp] = @@ -32,7 +32,7 @@ div( cls("mt-2 flex items-center text-sm text-gray-500 sm:mt-0"), prop.icon.map(_.element), - prop.text + prop.text.toString ) given HtmlComponent[Paragraph, Label] = @@ -69,7 +69,7 @@ cls := "flex items-center justify-between", p( cls := "text-sm font-medium text-indigo-600 truncate", - i.title + i.title.toString ), div( cls := "ml-2 flex-shrink-0 flex", @@ -105,7 +105,7 @@ cls( "z-10 sticky top-0 border-t border-b border-gray-200 bg-gray-50 px-6 py-1 text-sm font-medium text-gray-500" ), - i.title + i.title.toString ), ul( role := "list", diff --git a/ui/model/src/Form.scala b/ui/model/src/Form.scala new file mode 100644 index 0000000..d9a978f --- /dev/null +++ b/ui/model/src/Form.scala @@ -0,0 +1,17 @@ +package works.iterative +package ui.model + +case class FormItem[Value]( + id: String, + label: OneLine, + description: Option[Paragraph], + value: Value +) + +case class FormSection( + header: OneLine, + description: Option[Paragraph], + items: List[FormItem[_]] +) + +case class Form(sections: List[FormSection]) diff --git a/ui/model/src/ItemList.scala b/ui/model/src/ItemList.scala index 7c56254..3aa7815 100644 --- a/ui/model/src/ItemList.scala +++ b/ui/model/src/ItemList.scala @@ -5,17 +5,17 @@ ) case class ItemProp( - text: String, + text: OneLine, icon: Option[Icon] = None ) case class ListSection( - title: String, + title: OneLine, items: List[ListItem] ) case class ListItem( - title: String, + title: OneLine, href: String, label: Option[Label] = None, leftProps: List[ItemProp] = Nil, diff --git a/ui/model/src/Label.scala b/ui/model/src/Label.scala index 19741fd..6d6f13f 100644 --- a/ui/model/src/Label.scala +++ b/ui/model/src/Label.scala @@ -1,3 +1,5 @@ package works.iterative.ui.model +// TODO: Rename to Tag? Metals does not like Label for some reason, never imports it as code action +// A conflict with something in Laminar case class Label(color: HighlightColor, text: String) diff --git a/ui/model/src/Text.scala b/ui/model/src/Text.scala new file mode 100644 index 0000000..1ac70f0 --- /dev/null +++ b/ui/model/src/Text.scala @@ -0,0 +1,32 @@ +package works.iterative +package ui.model + +type Text = OneLine | Paragraph | List[Paragraph] + +// TODO: rename to MultiLine +opaque type Paragraph = String + +object Paragraph: + def apply(text: String): Paragraph = text + + given Conversion[String, Paragraph] with + def apply(text: String): Paragraph = text + + given Conversion[Paragraph, String] with + def apply(text: Paragraph): String = text + + extension (p: Paragraph) def toString: String = p + +opaque type OneLine = String + +object OneLine: + // TODO: check that the string actually is one line + def apply(text: String): OneLine = text + + given Conversion[String, OneLine] with + def apply(text: String): OneLine = text + + given Conversion[OneLine, String] with + def apply(text: OneLine): String = text + + extension (p: OneLine) def toString: String = p