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

com.dispalt.vdom.Frag.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Dan Di Spaltro
 *
 * 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 com.dispalt.vdom

import sri.core.{ ReactElement, ReactNode }

/**
  * Marker sub-type of [[TagMod]] which signifies that that type can be
  * rendered as a standalone fragment of [[ReactNode]].
  */
trait Frag extends TagMod {
  def render: ReactElement
}

trait DomFrag extends Frag {
  final def applyTo(b: Builder): Unit =
    b.appendChild(this.render)
}

final class SeqFrag[A](xs: Seq[A])(implicit ev: A => Frag) extends Frag {
  override def applyTo(t: Builder): Unit =
    xs.foreach(_.applyTo(t))

  override def render: ReactElement = {
    val b = new Builder()
    applyTo(b)
    b.render("")
  }
}

final case class ReactNodeFrag(render: ReactElement) extends DomFrag

class ReactTagOf[+N <: TopNode] private[vdom] (
    val tag: String,
    val modifiers: List[Seq[TagMod]],
    val namespace: Namespace
) extends DomFrag {

  def copy(
      tag: String = this.tag,
      modifiers: List[Seq[TagMod]] = this.modifiers,
      namespace: Namespace = this.namespace
  ): ReactTagOf[N] =
    new ReactTagOf(tag, modifiers, namespace)

  override def render: ReactElement = {
    val b = new Builder()
    build(b)
    b.render(tag)
  }

  /**
    * Walks the [[modifiers]] to apply them to a particular [[Builder]].
    * Super sketchy/procedural for max performance.
    */
  private[this] def build(b: Builder): Unit = {
    var current = modifiers
    val arr     = new Array[Seq[TagMod]](modifiers.length)

    var i = 0
    while (current != Nil) {
      arr(i) = current.head
      current = current.tail
      i += 1
    }

    var j = arr.length
    while (j > 0) {
      j -= 1
      val frag = arr(j)
      var i    = 0
      while (i < frag.length) {
        frag(i).applyTo(b)
        i += 1
      }
    }
  }

  def apply(xs: TagMod*): ReactTagOf[N] =
    this.copy(modifiers = xs :: modifiers)

  override def toString =
    render.toString
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy