All Downloads are FREE. Search and download functionalities are using the official Maven repository.

korolev.Component.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2018 Aleksey Fomkin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package korolev

import korolev.Context._
import korolev.execution.Scheduler
import korolev.state.{StateDeserializer, StateSerializer}
import levsha.Document.Node

import scala.util.Random

/**
  * Component definition. Every Korolev application is a component.
  * Extent it to declare component in object oriented style.
  *
  * @param id Unique identifier of the component.
  *           Use it when you create component declaration dynamically
  *
  * @tparam F Control monad
  * @tparam S State of the component
  * @tparam E Type of events produced by component
  */
abstract class Component
  [
    F[_]: Async: Scheduler,
    S: StateSerializer: StateDeserializer, P, E
  ](
    val initialState: S,
    val id: String = Component.randomId()
  ) {

  /**
    * Component context.
    *
    * {{{
    *  import context._
    *  import symbolDsl._
    * }}}
    */
  val context = Context[F, S, E]

  /**
    * Component render
    */
  def render(parameters: P, state: S): context.symbolDsl.Node
}

object Component {

  /** (context, state) => document */
  type Render[F[_], S, P, E] = (Context[F, S, E], P, S) => Node[Effect[F, S, E]]

  /**
    * Create component in functional style
    * @param f Component renderer
    * @see [[Component]]
    */
  def apply[F[_]: Async: Scheduler, S: StateSerializer: StateDeserializer, P, E]
           (initialState: S, id: String = Component.randomId())
           (f: Render[F, S, P, E]): Component[F, S, P, E] = {
    new Component[F, S, P, E](initialState, id) {
      def render(parameters: P, state: S): Node[Effect[F, S, E]] = f(context, parameters, state)
    }
  }

  final val TopLevelComponentId = "top-level"

  private[korolev] def randomId() = Random.alphanumeric.take(6).mkString
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy