Skip to content

Commit

Permalink
scala3 ongoing updates
Browse files Browse the repository at this point in the history
  • Loading branch information
aappddeevv committed Aug 28, 2022
1 parent 1b70094 commit 93b0138
Show file tree
Hide file tree
Showing 30 changed files with 352 additions and 249 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -46,3 +46,4 @@ scalajs-reaction-docs
/*.yml
.vscode
.ipy*
metals.sbt
4 changes: 3 additions & 1 deletion .scalafmt.conf
@@ -1,9 +1,11 @@
version = "3.0.0-RC3"
version = "3.0.6"
maxColumn = 120
#align = most
continuationIndent.defnSite = 2
assumeStandardLibraryStripMargin = true
docstrings = ScalaDoc
docstrings.wrapMaxColumn=80
docstrings.style = Asterisk
lineEndings = preserve
includeCurlyBraceInSelectChains = false
danglingParentheses = false
Expand Down
20 changes: 11 additions & 9 deletions README.md
@@ -1,22 +1,24 @@
<p align="center"><img width="200" src="./logo.svg"/></p>
<p align="center"><i>Use react hooks and scala.js to catch the best user experience.</i></p>

![scalajs-reaction](https://img.shields.io/maven-central/v/org.ttgoss.js/react_sjs1_3?versionPrefix=1.0.0-RC1) ![scala](https://img.shields.io/maven-central/v/org.scala-lang/scala3-compiler_3?versionSuffix=3.1.0)
scalajs-reaction: ![scalajs-reaction](https://img.shields.io/maven-central/v/org.ttgoss.js/react_sjs1_3?versionPrefix=1.0.0-RC1), scala: ![scala](https://img.shields.io/maven-central/v/org.scala-lang/scala3-compiler_3?versionSuffix=3.1.0)

scalajs reaction focuses on scala3 and easier integration into the js world.
scalajs reaction focuses on scala3 and interop with the react js world.

Use react version 18+ and/or the experimental to ensure that all hooks defined in this library are included in the underlying js source. Use the latest react-native.

Get started with the [docs](http://aappddeevv.github.io/scalajs-reaction)

Tiny example to declare a react component:
Here's how easy it is to declare a function component.

```scala
val HelloWorld: ReactFC0 = () => div("hello world")
```

# What is scalajs-reaction?

An interop library with reactjs and the react ecosystem.

This library is small and focuses on simple js function components and hooks. Hooks are described on the
[react](https://reactjs.org/docs/hooks-reference.html) page.

Expand All @@ -35,14 +37,14 @@ scalajs-reaction emphasizes:

`scalajs-reaction` allows you to build your entire interface in scalajs-reaction. As long as your front-end solution
can manage the model of
scala.js's output, you should consider scalajs-reaction for your solution. By providing a thin veneer over standard scala functions and hooks, it eschews abstractions and avoids getting in your way.
compiler scala.js's output, you should consider scalajs-reaction for your solution. By providing a thin veneer over standard scala functions and hooks, it eschews abstractions and avoids getting in your way.

- [Demo (WIP)](http://aappddeevv.github.io/scalajs-reaction/demo/index.html).
- [Live Coding](https://www.youtube.com/watch?v=7on-oT2Naco): Uses the old API but still helpful.

The react-native use-case for scala.js may actually be more
The react-native use-case for scala.js may be more
compelling than for web applications.
Support is provided for the experimental, concurrent API.
Support is provided for the experimental, reactjs concurrent API.

A g8 template is available. Use `sbt new aappddeevv/scalajs-reaction-app.g8` (in transition to scala3) to create a new project.

Expand Down Expand Up @@ -166,7 +168,7 @@ react function components are not pure functions and can never be pure functions
like a "context" that is established for some part of the DOM that also returns HTML builder
instructions each time it is called. If you come
from the java Spring world, think of it as a bean factory that knows how to emit render instructions.
It is better to think of react components not as a function but as an object.
It is better to think of react function components as an object and not as a function.

# Usage

Expand Down Expand Up @@ -292,8 +294,8 @@ complicated. You are likely only to use one set of react libraries
per application so you should not encounter any package namespace
collisions.

In many cases, the full package label has been dramatically shortened
to make it easier to import the content you need. The package names
In many cases, the full package label has been shortened
to make it easier to import the content. The package names
closely mirror the javascript libraries themselves.

You will most likely also need DOM bindings. Here's a link to the api
Expand Down
46 changes: 25 additions & 21 deletions build.sbt
Expand Up @@ -6,7 +6,7 @@ Global / onChangedBuildSource := ReloadOnSourceChanges

lazy val resolverSettings = Seq(
resolvers ++= Seq(
Resolver.sonatypeRepo("releases"),
//Resolver.sonatypeRepo("releases"),
//Resolver.jcenterRepo
)
)
Expand All @@ -23,8 +23,11 @@ val commonScalacOptions = Seq(
//"-Ywarn-value-discard",
//"-Ywarn-unused:imports,locals",
//,"-Ywarn-dead-code"
"source",
"future",
"-indent",
"-source",
"3.1",
"-new-syntax",
"-explain",
"-Ysafe-init",
"-Yexplicit-nulls",
//"-language:unsafeNulls",
Expand All @@ -36,7 +39,7 @@ lazy val jsSettings = Seq(
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
scalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(true))),
libraryDependencies ++= Seq(
("org.scala-js" %%% "scalajs-dom" % "2.0.0"),
("org.scala-js" %%% "scalajs-dom" % "2.2.0"),
),
// testing
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.7.10" % "test",
Expand All @@ -51,9 +54,9 @@ def buildinfo_settings(pkg: String) =
)

lazy val compilerSettings = Seq(
scalacOptions in (Compile, doc) ++= Seq("-groups"),
// not sure what this does anymore so removed it
//(doc / Compile / scalacOptions) ++= Seq("-groups"),
scalacOptions ++= commonScalacOptions,
//addCompilerPlugin(scalafixSemanticdb),
autoAPIMappings := true,
autoCompilerPlugins := true
)
Expand All @@ -78,15 +81,15 @@ lazy val publishSettings = Seq(
url("https://github.com/aappddeevv/scalajs-reaction"),
"scm:git:git@github.com:aappddeevv/scalajs-reaction.git")
),
publishArtifact in Test := false,
Test / publishArtifact := false,
// https://www.scala-sbt.org/1.x/docs/Publishing.html#Publishing
// should go to snapshots if isSnapshot.value is true
// nedeed to make sbt-sonatype: publishSigned work
publishTo := sonatypePublishToBundle.value,
sonatypeCredentialHost := "s01.oss.sonatype.org",
sonatypeProfileName := "org.ttgoss",
publishMavenStyle := true,
useGpg := true,
//useGpg := true,
credentials ++= (for {
keyid <- sys.env.get("GPG_KEY")
} yield Credentials("GnuPG Key ID", "gpg", keyid, "ignored")).toSeq,
Expand All @@ -110,11 +113,11 @@ def std_settings(p: String, d: String) =

inThisBuild(
List(
scalaVersion := "3.1.0",
scalaVersion := "3.1.3",
organization := "org.ttgoss.js",
organizationName := "The Trapelo Group (TTG) Open Source Software (TTGOSS)",
startYear := Some(2018),
scalafixDependencies += "com.nequissimus" %% "sort-imports" % "0.3.2",
//scalafixDependencies += "com.nequissimus" %% "sort-imports" % "0.3.2",
//,scalafmtOnCompile := true,
// should come from sbt-dynver
//version := "0.1.0-M7"
Expand All @@ -127,7 +130,7 @@ inThisBuild(

lazy val root = project
.in(file("."))
.settings(skip in publish := true)
.settings(publish / skip := true)
.aggregate(
//apollo,
apollo3,
Expand Down Expand Up @@ -555,7 +558,7 @@ lazy val examples = project
.settings(fpsettings)
.settings(std_settings("examples", "Example web application"))
.settings(
skip in publish := true,
publish / skip := true,
// Watch non-scala assets.
watchSources += baseDirectory.value / "examples/src/main/assets",
libraryDependencies ++= Seq(
Expand All @@ -576,21 +579,22 @@ lazy val examples = project
)
.enablePlugins(ScalaJSPlugin, BuildInfoPlugin)
.settings(buildinfo_settings("ttg.examples"))
.settings(artifactPath.in(Compile, fastOptJS) := crossTarget.in(Compile, fastOptJS).value / "Scala.js")
.settings(artifactPath.in(Compile, fullOptJS) := crossTarget.in(Compile, fullOptJS).value / "Scala.js")
.settings(Compile / fastOptJS / artifactPath := (Compile / fastOptJS / crossTarget).value / "Scala.js")
//.settings(Compile / fullOptJS / artifactPath := crossTarget.in(Compile, fullOptJS).value / "Scala.js")
.settings(Compile / fullOptJS / artifactPath := (Compile / fullOptJS / crossTarget).value / "Scala.js")

lazy val docs = project
.in(file("scalajs-reaction-docs"))
.settings(std_settings("scalajs-reaction-docs", "docs fake project"))
.settings(
skip.in(publish) := true
publish / skip := true
//,mdocVariables := Map("VERSION" -> version.value)
//scalacOptions -= -"Yno-imports",
//scalacOptions -= "-Ydata-warnings",
,
unidocProjectFilter in (ScalaUnidoc, unidoc) := inAnyProject -- inProjects(examples),// -- inProjects(apollo),
target in (ScalaUnidoc, unidoc) := (baseDirectory in LocalRootProject).value / "website" / "scalajs-reaction" / "static" / "api",
cleanFiles += (target in (ScalaUnidoc, unidoc)).value
ScalaUnidoc / unidoc / unidocProjectFilter := inAnyProject -- inProjects(examples),// -- inProjects(apollo),
ScalaUnidoc / unidoc / target := (LocalRootProject / baseDirectory).value / "website" / "scalajs-reaction" / "static" / "api",
cleanFiles += (ScalaUnidoc / unidoc / target).value
)
.enablePlugins(ScalaJSPlugin, ScalaUnidocPlugin)
// keep this list in sync with root, or filter the dependencies directly from root...
Expand Down Expand Up @@ -653,19 +657,19 @@ addCommandAlias("check", "all scalafmtSbtCheck scalafmtCheck")

val npmBuild = taskKey[Unit]("fullOptJS then webpack")
npmBuild := {
(fullOptJS in (examples, Compile)).value
(examples / Compile / fullOptJS).value
"npm run examples" !
}

val npmBuildFast = taskKey[Unit]("fastOptJS then webpack")
npmBuildFast := {
(fastOptJS in (examples, Compile)).value
(examples / Compile / fastOptJS).value
"npm run examples:dev" !
}

val npmRunDemo = taskKey[Unit]("fastOptJS then run webpack server")
npmRunDemo := {
(fastOptJS in (examples, Compile)).value
(examples / Compile / fastOptJS).value
"npm run examples:dev:start" !
}

Expand Down
9 changes: 5 additions & 4 deletions components/fabric/src/main/scala/components/Label.scala
Expand Up @@ -29,7 +29,7 @@ import react.*
import vdom.*
import fabric.styling.*

object Label {
object Label:
@js.native
@JSImport("office-ui-fabric-react/lib/Label", "Label")
object JS extends ReactJSComponent
Expand All @@ -50,10 +50,11 @@ object Label {
with ComponentRef[js.Any]
with Disabled
with Theme
with ReactJSProps {
with MaybeHasStrKey
with ReactJSProps:
var styles: js.UndefOr[IStyleFunctionOrObject[StyleProps, Styles]] = js.undefined
//var key: js.UndefOr[react.KeyType] = js.undefined
var required: js.UndefOr[Boolean] = js.undefined
}

trait StyleProps extends js.Object:
var className: js.UndefOr[String] = js.undefined
Expand All @@ -63,4 +64,4 @@ object Label {

trait Styles extends IStyleSetTag:
var root: js.UndefOr[IStyle] = js.undefined
}

6 changes: 2 additions & 4 deletions components/mssql/src/main/scala/mssql/package.scala
Expand Up @@ -19,9 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package mssql
import scala.scalajs.js

package object mssql {
import mssql.SchemaColumn
type Schema = js.Dictionary[SchemaColumn]
}
type Schema = js.Dictionary[mssql.SchemaColumn]
4 changes: 1 addition & 3 deletions components/node-fetch/src/main/scala/node-fetch.scala
@@ -1,11 +1,9 @@
package node_fetch

import scala.scalajs.js
import js.|
import scala.scalajs.js.annotation._
import scala.scalajs.js.annotation.*
import scala.scalajs.js.typedarray.{ArrayBuffer, Uint8Array}


@js.native
@JSImport("node-fetch", "fetch")
def fetch(
Expand Down
32 changes: 18 additions & 14 deletions components/node-fetch/src/main/scala/package.scala
@@ -1,17 +1,21 @@
package node_fetch

import scala.scalajs.js
import js.|
import scala.scalajs.js.annotation._
import scala.scalajs.js.annotation.*
import scala.scalajs.js.typedarray.{ArrayBuffer, Uint8Array}

package object node_fetch {
type RequestInfo = String | Request
type HeadersInit =
Headers | Sequence[Sequence[ByteString]] | OpenEndedDictionary[ByteString]
type ByteString = String

/** Keep the type simple so we don't have to pull in Blob, BufferSource, FormData, URLSearchParams. */
type BodyInit = String | js.Any
//Blob | BufferSource | FormData | String //todo: add URLSearchParams
type Sequence[T] = js.Array[T]
type OpenEndedDictionary[T] = js.Dictionary[T]
}
type RequestInfo = String | Request

type HeadersInit =
Headers | Sequence[Sequence[ByteString]] | OpenEndedDictionary[ByteString]

type ByteString = String

/** Keep the type simple so we don't have to pull in Blob, BufferSource, FormData, URLSearchParams. */
type BodyInit = String | js.Any

//Blob | BufferSource | FormData | String //todo: add URLSearchParams
type Sequence[T] = js.Array[T]

type OpenEndedDictionary[T] = js.Dictionary[T]

11 changes: 8 additions & 3 deletions jshelpers/src/main/scala/any.scala
Expand Up @@ -30,6 +30,11 @@ object any:
import scala.scalajs.js
import scala.language.unsafeNulls

/** Totally unsafe. */
extension (a: scala.Any)
/** Totally unsafe, use at your own risk! */
def unsafeAsJsAny = a.asInstanceOf[js.Any]

/** All of these are unsafe. */
extension [T <: js.Any](a: T)
/** Convert T => T|Null. */
Expand Down Expand Up @@ -100,13 +105,13 @@ object any:
/** If value is null or undefined be undefined, otherwise defined. Could be called "filterNull". */
def toNonNullUndefOr: js.UndefOr[T] =
// we keep this so that it works when needed
if (a == null || js.isUndefined(a)) js.undefined
if a == null || js.isUndefined(a) then js.undefined
else js.defined(a)

/** If value is null or undefined be None, else Some. */
def toNonNullOption: Option[T] =
// also defined in react package, repeated here
if (js.isUndefined(a) || a == null) None
if js.isUndefined(a) || a == null then None
else Option(a)

/** Equivalent `!!x` for some javascript value x. */
Expand All @@ -128,7 +133,7 @@ object any:
* }}}
*/
def toTruthyUndefOr: js.UndefOr[T] =
if (js.DynamicImplicits.truthValue(a.asInstanceOf[js.Dynamic])) js.defined(a)
if js.DynamicImplicits.truthValue(a.asInstanceOf[js.Dynamic]) then js.defined(a)
else js.undefined
end extension

Expand Down
2 changes: 1 addition & 1 deletion jshelpers/src/main/scala/dynamic.scala
Expand Up @@ -88,7 +88,7 @@ object dynamic:

/** Uses truthiness to determine None, you may not want this. */
def toOption[T <: js.Object]: Option[T] =
if (js.DynamicImplicits.truthValue(jsdyn)) Some(jsdyn.asInstanceOf[T])
if js.DynamicImplicits.truthValue(jsdyn) then Some(jsdyn.asInstanceOf[T])
else None

// /** Null and undefined => None, otherwise Some. The safest conversion. */
Expand Down
4 changes: 2 additions & 2 deletions jshelpers/src/main/scala/instances.scala
Expand Up @@ -21,12 +21,12 @@

package jshelpers

trait AllInstances extends JSPromiseInstances
trait AllInstances extends syntax.JSPromiseInstances
//with ToLocaleStringInstances

/** Instances with everything but all so it can be subclassed elsewhere. */
trait InstancesTrait:
object jspromise extends JSPromiseInstances
object jspromise extends syntax.JSPromiseInstances
//object anyval extends ToLocaleStringInstances

/** Instances is the wrong concept here as these are not typeclass
Expand Down
1 change: 0 additions & 1 deletion jshelpers/src/main/scala/misc.scala
Expand Up @@ -23,7 +23,6 @@ package jshelpers
package syntax

import scala.scalajs.js
import js.|

object misc:
/**
Expand Down

0 comments on commit 93b0138

Please sign in to comment.