Skip to content

Commit f8566ca

Browse files
committed
Create simple component interfaces
1 parent 1b9c731 commit f8566ca

File tree

10 files changed

+167
-135
lines changed

10 files changed

+167
-135
lines changed

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ JsFn
212212
ScalaFn
213213
- _ -> _
214214

215-
s/mapCtorType/mapCtor/g
215+
-------------------
216216

217-
RawAccessMounted <-- something without the word Access in it...?
217+
add mapCtor? (in addition to mapCtorType)
218218

219219
is Callback necessary from non-render lifecycle hooks?
220220
DOM isn't used, is it really confusing?
@@ -230,6 +230,3 @@ upgrade to latest React
230230

231231
<!-- react-text: 19 -->Description<!-- /react-text -->
232232

233-
seprate BaseComponent into with/without .root & T0s
234-
replace usage in text, extra, ext-*
235-

core/src/main/scala/japgolly/scalajs/react/component/Generic.scala

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,87 +5,100 @@ import scala.scalajs.js
55
import japgolly.scalajs.react.internal._
66
import japgolly.scalajs.react.vdom
77
import japgolly.scalajs.react.{raw => RAW}
8-
import japgolly.scalajs.react.{Callback, CtorType, Key, PropsChildren, StateAccess}
8+
import japgolly.scalajs.react.{Callback, CallbackTo, CtorType, Key, PropsChildren, StateAccess}
99

1010
object Generic {
1111

12-
type ComponentRoot[P, CT[-p, +u] <: CtorType[p, u], U] = ComponentWithRoot[P, CT, U, P, CT, U]
13-
type UnmountedRoot[P, M] = UnmountedWithRoot[P, M, P, M]
14-
type MountedRoot[F[_], P, S] = MountedWithRoot[F, P, S, P, S]
15-
16-
@inline implicit def componentCtorOps[
17-
P1, CT1[-p, +u] <: CtorType[p, u], U1,
18-
P0, CT0[-p, +u] <: CtorType[p, u], U0](base: ComponentWithRoot[P1, CT1, U1, P0, CT0, U0]): CT1[P1, U1] =
19-
base.ctor
12+
@inline implicit def toComponentCtor[P, CT[-p, +u] <: CtorType[p, u], U](c: ComponentSimple[P, CT, U]): CT[P, U] =
13+
c.ctor
2014

2115
trait ComponentRaw {
2216
type Raw <: js.Any
2317
val raw: Raw
2418
def displayName: String
2519
}
2620

27-
trait ComponentWithRoot[
28-
P1, CT1[-p, +u] <: CtorType[p, u], U1,
29-
P0, CT0[-p, +u] <: CtorType[p, u], U0] extends ComponentRaw {
21+
trait ComponentSimple[P, CT[-p, +u] <: CtorType[p, u], U] extends ComponentRaw {
22+
final type Props = P
23+
final type Unmounted = U
3024

31-
final type Props = P1
32-
final type Unmounted = U1
25+
def cmapCtorProps[P2](f: P2 => P): ComponentSimple[P2, CT, U]
26+
def mapUnmounted[U2](f: U => U2): ComponentSimple[P, CT, U2]
27+
def mapCtorType[CT2[-p, +u] <: CtorType[p, u]](f: CT[P, U] => CT2[P, U])(implicit pf: Profunctor[CT2]): ComponentSimple[P, CT2, U]
28+
29+
val ctor: CT[P, U]
30+
implicit def ctorPF: Profunctor[CT]
31+
}
3332

33+
trait ComponentWithRoot[P1, CT1[-p, +u] <: CtorType[p, u], U1, P0, CT0[-p, +u] <: CtorType[p, u], U0] extends ComponentSimple[P1, CT1, U1] {
3434
type Root <: ComponentRoot[P0, CT0, U0]
3535
def root: Root
3636

37-
def cmapCtorProps[P2](f: P2 => P1): ComponentWithRoot[P2, CT1, U1, P0, CT0, U0]
38-
def mapUnmounted[U2](f: U1 => U2): ComponentWithRoot[P1, CT1, U2, P0, CT0, U0]
39-
def mapCtorType[CT2[-p, +u] <: CtorType[p, u]](f: CT1[P1, U1] => CT2[P1, U1])(implicit pf: Profunctor[CT2]): ComponentWithRoot[P1, CT2, U1, P0, CT0, U0]
40-
41-
val ctor: CT1[P1, U1]
42-
implicit def ctorPF: Profunctor[CT1]
37+
override def cmapCtorProps[P2](f: P2 => P1): ComponentWithRoot[P2, CT1, U1, P0, CT0, U0]
38+
override def mapUnmounted[U2](f: U1 => U2): ComponentWithRoot[P1, CT1, U2, P0, CT0, U0]
39+
override def mapCtorType[CT2[-p, +u] <: CtorType[p, u]](f: CT1[P1, U1] => CT2[P1, U1])(implicit pf: Profunctor[CT2]): ComponentWithRoot[P1, CT2, U1, P0, CT0, U0]
4340
}
4441

42+
type ComponentRoot[P, CT[-p, +u] <: CtorType[p, u], U] = ComponentWithRoot[P, CT, U, P, CT, U]
43+
44+
// ===================================================================================================================
45+
46+
type Unmounted[P, M] = UnmountedSimple[P, M]
47+
4548
trait UnmountedRaw {
4649
type Raw <: RAW.ReactElement
4750
val raw: Raw
4851
def displayName: String
4952
}
5053

51-
trait UnmountedWithRoot[P1, M1, P0, M0] extends UnmountedRaw {
52-
final type Props = P1
53-
final type Mounted = M1
54-
55-
type Root <: UnmountedRoot[P0, M0]
56-
def root: Root
54+
trait UnmountedSimple[P, M] extends UnmountedRaw {
55+
final type Props = P
56+
final type Mounted = M
5757

58-
def mapUnmountedProps[P2](f: P1 => P2): UnmountedWithRoot[P2, M1, P0, M0]
59-
def mapMounted[M2](f: M1 => M2): UnmountedWithRoot[P1, M2, P0, M0]
58+
def mapUnmountedProps[P2](f: P => P2): UnmountedSimple[P2, M]
59+
def mapMounted[M2](f: M => M2): UnmountedSimple[P, M2]
6060

6161
def vdomElement: vdom.VdomElement
6262
def key: Option[Key]
6363
def ref: Option[String]
6464
def props: Props
6565
def propsChildren: PropsChildren
6666

67-
val mountRaw: RAW.ReactComponent => M1
67+
val mountRaw: RAW.ReactComponent => M
6868

6969
def renderIntoDOM(container: RAW.ReactDOM.Container, callback: Callback = Callback.empty): Mounted =
7070
mountRaw(RAW.ReactDOM.render(raw, container, callback.toJsFn))
7171
}
7272

73+
trait UnmountedWithRoot[P1, M1, P0, M0] extends UnmountedSimple[P1, M1] {
74+
type Root <: UnmountedRoot[P0, M0]
75+
def root: Root
76+
77+
override def mapUnmountedProps[P2](f: P1 => P2): UnmountedWithRoot[P2, M1, P0, M0]
78+
override def mapMounted[M2](f: M1 => M2): UnmountedWithRoot[P1, M2, P0, M0]
79+
}
80+
81+
type UnmountedRoot[P, M] = UnmountedWithRoot[P, M, P, M]
82+
83+
// ===================================================================================================================
84+
85+
type Mounted[F[_], P, S] = MountedSimple[F, P, S]
86+
type MountedPure [P, S] = MountedSimple[CallbackTo, P, S]
87+
type MountedImpure[P, S] = MountedSimple[Effect.Id, P, S]
88+
7389
trait MountedRaw {
7490
type Raw <: RAW.ReactComponent
7591
val raw: Raw
7692
def displayName: String
7793
}
7894

79-
trait MountedWithRoot[F[_], P1, S1, P0, S0] extends MountedRaw with StateAccess[F, S1] {
80-
final type Props = P1
95+
trait MountedSimple[F[_], P, S] extends MountedRaw with StateAccess[F, S] {
96+
final type Props = P
8197

82-
type Root <: MountedRoot[F, P0, S0]
83-
def root: Root
84-
85-
override type WithEffect[F2[_]] <: MountedWithRoot[F2, P1, S1, P0, S0]
86-
override type WithMappedState[S2] <: MountedWithRoot[F, P1, S2, P0, S0]
87-
type WithMappedProps[P2] <: MountedWithRoot[F, P2, S1, P0, S0]
88-
def mapProps[P2](f: P1 => P2): WithMappedProps[P2]
98+
override type WithEffect[F2[_]] <: MountedSimple[F2, P, S]
99+
override type WithMappedState[S2] <: MountedSimple[F, P, S2]
100+
type WithMappedProps[P2] <: MountedSimple[F, P2, S]
101+
def mapProps[P2](f: P => P2): WithMappedProps[P2]
89102

90103
def isMounted: F[Boolean]
91104
def getDOMNode: F[dom.Element]
@@ -95,5 +108,16 @@ object Generic {
95108
def forceUpdate(callback: Callback): F[Unit]
96109
final def forceUpdate: F[Unit] = forceUpdate(Callback.empty)
97110
}
111+
112+
trait MountedWithRoot[F[_], P1, S1, P0, S0] extends MountedSimple[F, P1, S1] {
113+
type Root <: MountedRoot[F, P0, S0]
114+
def root: Root
115+
116+
override type WithEffect[F2[_]] <: MountedWithRoot[F2, P1, S1, P0, S0]
117+
override type WithMappedState[S2] <: MountedWithRoot[F, P1, S2, P0, S0]
118+
override type WithMappedProps[P2] <: MountedWithRoot[F, P2, S1, P0, S0]
119+
}
120+
121+
type MountedRoot[F[_], P, S] = MountedWithRoot[F, P, S, P, S]
98122
}
99123

core/src/main/scala/japgolly/scalajs/react/component/Js.scala

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -54,97 +54,86 @@ object Js extends JsBaseComponentTemplate[RAW.ReactClass] {
5454

5555
// ===================================================================================================================
5656

57-
type UnmountedRoot[P <: js.Object, M] = UnmountedWithRoot[P, M, P, M]
57+
sealed trait UnmountedSimple[P, M] extends Generic.UnmountedSimple[P, M] {
58+
override def mapUnmountedProps[P2](f: P => P2): UnmountedSimple[P2, M]
59+
override def mapMounted[M2](f: M => M2): UnmountedSimple[P, M2]
5860

59-
sealed trait UnmountedWithRoot[P1, M1, P0 <: js.Object, M0]
60-
extends Generic.UnmountedWithRoot[P1, M1, P0, M0] {
61+
override final type Raw = RAW.ReactComponentElement
62+
override final def displayName = raw.`type`.displayName
63+
}
6164

65+
sealed trait UnmountedWithRoot[P1, M1, P0 <: js.Object, M0] extends UnmountedSimple[P1, M1] with Generic.UnmountedWithRoot[P1, M1, P0, M0] {
6266
override final type Root = UnmountedRoot[P0, M0]
63-
override final type Raw = RAW.ReactComponentElement
6467
override def mapUnmountedProps[P2](f: P1 => P2): UnmountedWithRoot[P2, M1, P0, M0]
6568
override def mapMounted[M2](f: M1 => M2): UnmountedWithRoot[P1, M2, P0, M0]
66-
67-
override final def displayName = raw.`type`.displayName
6869
}
6970

71+
type UnmountedRoot[P <: js.Object, M] = UnmountedWithRoot[P, M, P, M]
72+
7073
def unmountedRoot[P <: js.Object, M](r: RAW.ReactComponentElement, m: RAW.ReactComponent => M): UnmountedRoot[P, M] =
7174
new UnmountedRoot[P, M] {
72-
73-
override def root = this
74-
override val raw = r
75-
override val mountRaw = m
76-
77-
override val vdomElement =
78-
vdom.VdomElement(raw)
79-
80-
override def key: Option[Key] =
81-
jsNullToOption(raw.key)
82-
83-
override def ref: Option[String] =
84-
jsNullToOption(raw.ref)
85-
86-
override def props: P =
87-
raw.props.asInstanceOf[P]
88-
89-
override def propsChildren: PropsChildren =
90-
PropsChildren.fromRawProps(raw.props)
91-
92-
override def mapUnmountedProps[P2](f: P => P2) =
93-
mappedU(this)(f, identityFn)
94-
95-
override def mapMounted[M2](f: M => M2) =
96-
mappedU(this)(identityFn, f)
75+
override def root = this
76+
override val raw = r
77+
override val mountRaw = m
78+
override val vdomElement = vdom.VdomElement(raw)
79+
override def key = jsNullToOption(raw.key)
80+
override def ref = jsNullToOption(raw.ref)
81+
override def props = raw.props.asInstanceOf[P]
82+
override def propsChildren = PropsChildren.fromRawProps(raw.props)
83+
override def mapUnmountedProps[P2](f: P => P2) = mappedU(this)(f, identityFn)
84+
override def mapMounted[M2](f: M => M2) = mappedU(this)(identityFn, f)
9785
}
9886

99-
private def mappedU[P2, M2, P1, M1, P0 <: js.Object, M0]
100-
(from: UnmountedWithRoot[P1, M1, P0, M0])
101-
(mp: P1 => P2, mm: M1 => M2)
87+
private def mappedU[P2, M2, P1, M1, P0 <: js.Object, M0](from: UnmountedWithRoot[P1, M1, P0, M0])
88+
(mp: P1 => P2, mm: M1 => M2)
10289
: UnmountedWithRoot[P2, M2, P0, M0] =
10390
new UnmountedWithRoot[P2, M2, P0, M0] {
104-
override def root = from.root
105-
override def props = mp(from.props)
106-
override val raw = from.raw
107-
override def vdomElement = from.vdomElement
108-
override def key = from.key
109-
override def ref = from.ref
110-
override def propsChildren = from.propsChildren
111-
112-
override def mapUnmountedProps[P3](f: P2 => P3) =
113-
mappedU(from)(f compose mp, mm)
114-
115-
override def mapMounted[M3](f: M2 => M3) =
116-
mappedU(from)(mp, f compose mm)
117-
118-
override val mountRaw = mm compose from.mountRaw
91+
override def root = from.root
92+
override def props = mp(from.props)
93+
override val raw = from.raw
94+
override def vdomElement = from.vdomElement
95+
override def key = from.key
96+
override def ref = from.ref
97+
override def propsChildren = from.propsChildren
98+
override def mapUnmountedProps[P3](f: P2 => P3) = mappedU(from)(f compose mp, mm)
99+
override def mapMounted[M3](f: M2 => M3) = mappedU(from)(mp, f compose mm)
100+
override val mountRaw = mm compose from.mountRaw
119101
}
120102

121103
// ===================================================================================================================
122104

123-
type MountedRoot[F[_], P <: js.Object, S <: js.Object, R <: RawMounted] = MountedWithRoot[F, P, S, R, P, S]
105+
sealed trait MountedSimple[F[_], P, S, R <: RawMounted] extends Generic.MountedSimple[F, P, S] {
124106

125-
sealed trait MountedWithRoot[F[_], P1, S1, R <: RawMounted, P0 <: js.Object, S0 <: js.Object]
126-
extends Generic.MountedWithRoot[F, P1, S1, P0, S0] {
127-
128-
override final type Root = MountedRoot[F, P0, S0, R]
129-
override final type WithEffect[F2[_]] = MountedWithRoot[F2, P1, S1, R, P0, S0]
130-
override final type WithMappedProps[P2] = MountedWithRoot[F, P2, S1, R, P0, S0]
131-
override final type WithMappedState[S2] = MountedWithRoot[F, P1, S2, R, P0, S0]
107+
override type WithEffect[F2[_]] <: MountedSimple[F2, P, S, R]
108+
override type WithMappedProps[P2] <: MountedSimple[F, P2, S, R]
109+
override type WithMappedState[S2] <: MountedSimple[F, P, S2, R]
132110

133111
override final type Raw = R
134-
135112
override final def displayName = raw.constructor.displayName
136113

137-
final def withRawType[R2 <: RawMounted]: MountedWithRoot[F, P1, S1, R2, P0, S0] =
138-
this.asInstanceOf[MountedWithRoot[F, P1, S1, R2, P0, S0]]
139-
140-
final def addFacade[T <: js.Object]: MountedWithRoot[F, P1, S1, R with T, P0, S0] =
141-
withRawType[R with T]
142-
114+
def withRawType[R2 <: RawMounted]: MountedSimple[F, P, S, R2]
115+
def addFacade[T <: js.Object]: MountedSimple[F, P, S, R with T]
143116
// def getDefaultProps: Props
144117
// def getInitialState: js.Object | Null
145118
// def render(): ReactElement
146119
}
147120

121+
sealed trait MountedWithRoot[F[_], P1, S1, R <: RawMounted, P0 <: js.Object, S0 <: js.Object]
122+
extends MountedSimple[F, P1, S1, R] with Generic.MountedWithRoot[F, P1, S1, P0, S0] {
123+
override final type Root = MountedRoot[F, P0, S0, R]
124+
override final type WithEffect[F2[_]] = MountedWithRoot[F2, P1, S1, R, P0, S0]
125+
override final type WithMappedProps[P2] = MountedWithRoot[F, P2, S1, R, P0, S0]
126+
override final type WithMappedState[S2] = MountedWithRoot[F, P1, S2, R, P0, S0]
127+
128+
override final def withRawType[R2 <: RawMounted]: MountedWithRoot[F, P1, S1, R2, P0, S0] =
129+
this.asInstanceOf[MountedWithRoot[F, P1, S1, R2, P0, S0]]
130+
131+
override final def addFacade[T <: js.Object]: MountedWithRoot[F, P1, S1, R with T, P0, S0] =
132+
withRawType[R with T]
133+
}
134+
135+
type MountedRoot[F[_], P <: js.Object, S <: js.Object, R <: RawMounted] = MountedWithRoot[F, P, S, R, P, S]
136+
148137
def mountedRoot[P <: js.Object, S <: js.Object, R <: RawMounted](r: R): MountedRoot[Effect.Id, P, S, R] =
149138
new Template.MountedWithRoot[Effect.Id, P, S] with MountedRoot[Effect.Id, P, S, R] {
150139
override implicit def F = Effect.idInstance

core/src/main/scala/japgolly/scalajs/react/component/JsBaseComponentTemplate.scala

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,34 @@ trait JsBaseComponentTemplate[RawComponent <: js.Any] {
88

99
protected def rawComponentDisplayName: RawComponent => String
1010

11-
final type ComponentRoot[P <: js.Object, CT[-p, +u] <: CtorType[p, u], U] =
12-
ComponentWithRoot[P, CT, U, P, CT, U]
13-
1411
// Difference between this and its Generic counterpart:
1512
// - P0 has an upper bound of js.Object.
1613
// - Raw type specified
14+
15+
sealed trait ComponentSimple[P, CT[-p, +u] <: CtorType[p, u], U] extends Generic.ComponentSimple[P, CT, U] {
16+
override final type Raw = RawComponent
17+
override final def displayName = rawComponentDisplayName(raw)
18+
19+
override def cmapCtorProps[P2](f: P2 => P): ComponentSimple[P2, CT, U]
20+
override def mapUnmounted[U2](f: U => U2): ComponentSimple[P, CT, U2]
21+
override def mapCtorType[CT2[-p, +u] <: CtorType[p, u]](f: CT[P, U] => CT2[P, U])(implicit pf: Profunctor[CT2]): ComponentSimple[P, CT2, U]
22+
}
23+
1724
sealed trait ComponentWithRoot[
1825
P1, CT1[-p, +u] <: CtorType[p, u], U1,
1926
P0 <: js.Object, CT0[-p, +u] <: CtorType[p, u], U0]
20-
extends Generic.ComponentWithRoot[P1, CT1, U1, P0, CT0, U0] {
27+
extends ComponentSimple[P1, CT1, U1] with Generic.ComponentWithRoot[P1, CT1, U1, P0, CT0, U0] {
2128

2229
override final type Root = ComponentRoot[P0, CT0, U0]
23-
override final type Raw = RawComponent
24-
override final def displayName = rawComponentDisplayName(raw)
2530

2631
override def cmapCtorProps[P2](f: P2 => P1): ComponentWithRoot[P2, CT1, U1, P0, CT0, U0]
2732
override def mapUnmounted[U2](f: U1 => U2): ComponentWithRoot[P1, CT1, U2, P0, CT0, U0]
2833
override def mapCtorType[CT2[-p, +u] <: CtorType[p, u]](f: CT1[P1, U1] => CT2[P1, U1])(implicit pf: Profunctor[CT2]): ComponentWithRoot[P1, CT2, U1, P0, CT0, U0]
2934
}
3035

36+
final type ComponentRoot[P <: js.Object, CT[-p, +u] <: CtorType[p, u], U] =
37+
ComponentWithRoot[P, CT, U, P, CT, U]
38+
3139
final def componentRoot[P <: js.Object, CT[-p, +u] <: CtorType[p, u], U](rc: RawComponent, c: CT[P, U])
3240
(implicit pf: Profunctor[CT]): ComponentRoot[P, CT, U] =
3341
new ComponentRoot[P, CT, U] {

0 commit comments

Comments
 (0)