Skip to content
This repository was archived by the owner on Nov 20, 2025. It is now read-only.

Commit f6fc80f

Browse files
Reworked TextInput -> Input, and UIElementId -> UIKey
1 parent e4a8f32 commit f6fc80f

5 files changed

Lines changed: 116 additions & 127 deletions

File tree

sandbox-ui/src/main/scala/example/Model.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import cats.effect.IO
44
import tyrian.*
55
import tyrian.next.*
66
import tyrian.ui.*
7-
import tyrian.ui.input.TextInput
7+
import tyrian.ui.input.Input
88

99
final case class Model(
1010
topNav: TopNav,
11-
nameInput: TextInput
11+
nameInput: Input
1212
):
1313

1414
def update: GlobalMsg => Outcome[Model] =
@@ -34,7 +34,11 @@ final case class Model(
3434

3535
object Model:
3636
val init: Model =
37-
Model(TopNav.initial, TextInput(UIElementId("name-input")).withPlaceholder("Type here..."))
37+
Model(
38+
TopNav.initial,
39+
Input(UIKey("name-input"))
40+
.withPlaceholder("Type here...")
41+
)
3842

3943
def tmpView(m: Model)(using Theme): HtmlFragment =
4044
HtmlFragment(

tyrian-next/src/main/scala/tyrian/ui/UIElement.scala

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,18 @@ object UIElement:
2020

2121
trait Stateful[T] extends UIElement[T]:
2222

23-
def id: UIElementId
24-
def withId(value: UIElementId): T
23+
def key: UIKey
24+
def withKey(value: UIKey): T
2525

2626
def update: GlobalMsg => Outcome[T]
2727

28-
opaque type UIElementId = String
29-
object UIElementId:
30-
31-
given CanEqual[UIElementId, UIElementId] = CanEqual.derived
28+
/*
3229
33-
def apply(value: String): UIElementId = value
30+
Theme
3431
35-
extension (id: UIElementId) def value: String = id
32+
- NoStyles
3633
37-
/*
34+
---
3835
3936
Stateless Components
4037
- Text - DONE
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package tyrian.ui
2+
3+
opaque type UIKey = String
4+
5+
object UIKey:
6+
7+
given CanEqual[UIKey, UIKey] = CanEqual.derived
8+
9+
def apply(value: String): UIKey = value
10+
11+
extension (key: UIKey) def value: String = key
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package tyrian.ui.input
2+
3+
import tyrian.Elem
4+
import tyrian.EmptyAttribute
5+
import tyrian.Html.*
6+
import tyrian.next.GlobalMsg
7+
import tyrian.next.Outcome
8+
import tyrian.ui
9+
import tyrian.ui.Theme
10+
import tyrian.ui.UIElement
11+
import tyrian.ui.UIKey
12+
13+
final case class Input(
14+
key: UIKey,
15+
placeholder: String,
16+
isDisabled: Boolean,
17+
isReadOnly: Boolean,
18+
value: String,
19+
classNames: Set[String],
20+
overrideLocalTheme: Option[Theme => Theme]
21+
) extends UIElement.Stateful[Input]:
22+
23+
def withPlaceholder(placeholder: String): Input =
24+
this.copy(placeholder = placeholder)
25+
26+
def withDisabled(disabled: Boolean): Input =
27+
this.copy(isDisabled = disabled)
28+
def enabled: Input =
29+
withDisabled(false)
30+
def disabled: Input =
31+
withDisabled(true)
32+
33+
def withReadonly(readOnly: Boolean): Input =
34+
this.copy(isReadOnly = readOnly)
35+
def readOnly: Input =
36+
withReadonly(true)
37+
def editable: Input =
38+
withReadonly(false)
39+
40+
def withValue(value: String): Input =
41+
this.copy(value = value)
42+
43+
def withKey(value: UIKey): Input =
44+
this.copy(key = value)
45+
46+
def withClassNames(classes: Set[String]): Input =
47+
this.copy(classNames = classes)
48+
49+
def withThemeOverride(f: Theme => Theme): Input =
50+
this.copy(overrideLocalTheme = Some(f))
51+
52+
def update: GlobalMsg => Outcome[Input] =
53+
case TextInputMsg.Changed(_key, v) if _key == key =>
54+
Outcome(this.copy(value = v))
55+
56+
case TextInputMsg.Clear(_key) if _key == key =>
57+
Outcome(this.copy(value = ""))
58+
59+
case _ =>
60+
Outcome(this)
61+
62+
def view: Theme ?=> Elem[GlobalMsg] =
63+
val disabledAttr = if isDisabled then attribute("disabled", "true") else EmptyAttribute
64+
val readonlyAttr = if isReadOnly then attribute("readonly", "true") else EmptyAttribute
65+
66+
val inputAttrs = List(
67+
tyrian.Html.placeholder := placeholder,
68+
tyrian.Html.value := value,
69+
typ := "text",
70+
onInput((s: String) => TextInputMsg.Changed(key, s)),
71+
disabledAttr,
72+
readonlyAttr
73+
)
74+
75+
input(inputAttrs*)
76+
77+
object Input:
78+
79+
def apply(key: UIKey): Input =
80+
Input(
81+
key,
82+
placeholder = "",
83+
isDisabled = false,
84+
isReadOnly = false,
85+
value = "",
86+
Set.empty,
87+
None
88+
)
89+
90+
enum TextInputMsg extends GlobalMsg:
91+
case Changed(id: UIKey, value: String)
92+
case Clear(id: UIKey)

tyrian-next/src/main/scala/tyrian/ui/input/TextInput.scala

Lines changed: 0 additions & 115 deletions
This file was deleted.

0 commit comments

Comments
 (0)