Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 16 23:01
    scala-steward closed #500
  • Sep 16 23:01
    scala-steward commented #500
  • Sep 16 23:01
    scala-steward opened #509
  • Sep 15 00:26
    scala-steward closed #481
  • Sep 15 00:26
    scala-steward commented #481
  • Sep 15 00:26
    scala-steward opened #508
  • Sep 13 16:57
    Asamsig commented #456
  • Sep 13 12:28
    dkirchhof commented #498
  • Sep 13 12:27
    dkirchhof closed #498
  • Sep 13 12:27
    dkirchhof commented #498
  • Sep 12 03:49

    shadaj on v0.6.8

    (compare)

  • Sep 11 22:16

    shadaj on act-facade

    (compare)

  • Sep 11 22:16

    shadaj on external-component-export

    (compare)

  • Sep 11 22:16

    shadaj on scala-2.13-any

    (compare)

  • Sep 11 22:16

    shadaj on intellij-standalone-plugin

    (compare)

  • Sep 11 20:57

    shadaj on master

    Release v0.6.8 (compare)

  • Sep 11 20:43
    shadaj demilestoned #495
  • Sep 11 20:43
    shadaj milestoned #495
  • Sep 11 17:54

    shadaj on master

    Remove errant println (#507) (compare)

  • Sep 11 17:54
    shadaj closed #507
Alexander Samsig
@asamsig:matrix.org
[m]
I'm afraid the best way to do it, would be to have entry points in TypeScript/JavaScript and simply import and export Slinky components in them, since you can't make scalajs output a folder structure that Next.js would like.
I've debated doing some Webpack magic, but I doubt it would work well
shadaj
@shadaj:matrix.org
[m]
Ah, nice. I guess you might need to manually write or generate some glue JS code that can present separate "pages" to Next.js while routing to a common Scala.js library under the hood.
Yep, probably best to avoid Webpack magic, that tends to create trouble later on. It would be super cool to see if Scala.js' bundle splitting works with the glue pages approach, since the async imports that Next.js uses could result in much smaller chunks.
Alexander Samsig
@asamsig:matrix.org
[m]
The downsides is two build tools, currently I've experimented with the new module splitting.
shadaj
@shadaj:matrix.org
[m]
I guess eventually there could be an SBT plugin that wraps around the Next.js CLI tools, but probably will be more work than the benefit of saving a terminal tab while you're still in prototyping mode 😄
Alexander Samsig
@asamsig:matrix.org
[m]
Haha, absolutely, Next.js is also very opinionated, so much easier to just let it be, and use JS glue code to bring in Slinky components.
Currently I'm exporting Slinky components directly, and that actually works too, but unfortunately the routing in Next.js is based on folder structure, which is probably not feasible to achieve with pure Scala.js.
I think I'll proceed with the glue code approach, and see if I can port one of the official Next.js samples to Slinky.
Alexander Samsig
@asamsig:matrix.org
[m]

shadaj: I hit my first real hurdle, do you have any suggestions on how to do this in Slinky?

function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

It is for making a base component that is responsible for initializing all pages, see https://nextjs.org/docs/advanced-features/custom-app for more info.

Alexander Samsig
@asamsig:matrix.org
[m]
shadaj: I've managed to create a very basic Next.js app now with Slinky, I'm just following along the "Create Next.js app", it is actually working quite well, though I did encounter some issues with ModuleSplitStyle.SmallestModules + Class components + fastLinkJS, the error message said that java.lang.object reference was undefined or something similar, fullLinkJS worked fine though. I fixed it by removing the last Class component I had, since it was just for testing class components anyway.
It did work with ModuleSplitStyle.FewestModules, but then compilation with Next.js took several seconds, so really not an option, but who needs class components anyway! ;)
The link is here: https://github.com/Asamsig/next-slinky-example
shadaj
@shadaj:matrix.org
[m]
Alexander Samsig: you'll have to treat Component as a ReactComponentClass[js.Object], then wrap it into a local ExternalComponent so that you can construct it with the given props
awesome to see the example! I'll investigate what's going on with ModuleSplitStyle.SmallestModules, there are some hacks that Slinky uses that depend on a couple of Scala.js internals so it is possible that those are breaking
1 reply
evbo
@evbo

I have a callback function for a Select Input that the javascript library sends me a simple object of what was selected: {label: String, value: String}

If I let Slinky's Reader deserialize this for me though I get (from js console):

e$2: $c_Lcom_me_data_FieldOption
Lcom_me_data_FieldOption__f_label: "New Feature"
Lcom_me_data_FieldOption__f_value: "feature"

This works fine for scalajs, but the issue is that inside my callback I need to yet again call another js function, passing it this object. It doesn't like seeing the fully qualified names of course.

Is this kind of interop in slinky supported?

evbo
@evbo
of course, I can just convert my FieldOption into a js.Object but Im wonering if there's automation for this?:
jsCallbackInsideMyScalajsCallback(
  js.Dynamic.literal("label" -> fieldOption.label, "value" -> fieldOption.value)
)
evbo
@evbo

and another smaller question, how do you get external objects to appear as "ReactElement"? For instance, I am importing an icon:

@js.native
@JSImport("@atlaskit/icon/glyph/unlock", JSImport.Default)
object UnlockIcon extends js.Object

And if I put it as the button text it complains it is not of type ReactElement

shadaj
@shadaj:matrix.org
[m]
@evbo: you can just have the UnlockIcon extend ReactElement instead of js.Object
Alexander Samsig: that would be very helpful! does SmallestModules work with functional components?
2 replies
evbo
@evbo
doh! so obvious thanks. What about the deserialization I posted above - have you seen that before? My hack is pretty brutal but works
Oleg Pyzhcov
@oleg-py
Are there any developments on Scala 3 support?
shadaj
@shadaj:matrix.org
[m]
Alexander Samsig: thanks for the repro! will take a look, but it does sound like it could just be a Scala.js bug
@oleg-py: not yet, unfortunately haven't gotten the time to work on it yet. The main work is porting Reader/Writer derivation, since @react isn't required to use Slinky
evbo
@evbo

sometimes i find js.Any to be suitable as a type (usually in avoiding overly complex union types) for when I have no really breakable logic interacting with a given variable, but at some point I need to convert a case class to that js.Any type.

How do I tell slinky to convert my case class to a js.Any explicity so that the attributes have the same names as the case class in the javascript?

mn98
@mn98

Hi all, I have a feeling this question is extremely basic, but I can't find a working example. When I try to add readOnly := true to a textarea like so:

        textarea(
          rows := props.numberOfRows.toString,
          cols := props.numberOfColumns.toString,
          readOnly := true,
          defaultValue := "Blah"
        )

I get the following compilation error:

 found   : slinky.core.AttrPair[slinky.web.html._readOnly_attr.type]
 required: slinky.core.TagMod[slinky.web.html.textarea.tag.type]]

could someone please educate me here on how this is achieved?

mn98
@mn98

Ah, I got the above working like this:

    private val readOnlyAttr = CustomAttribute[Boolean]("readOnly")

    textarea(
      rows := props.numberOfRows.toString,
      cols := props.numberOfColumns.toString,
      readOnlyAttr := true,
      defaultValue := "Blah"
    )

Would someone mind pointing me in the direction of some learning materials on why the custom things are necessary? I'm very green in the world of html!

2 replies
mn98
@mn98

Hi all, I hope this is the right place to ask about slinky-styled-components. Whilst getting started with this (using version 0.1.0+10-b09028e5) I've experimented with a simple styled div:

    val divRef = useRef[Div](null)
    val styledDiv = styled.div(css"""width: 100%; height: 640px;""")
    styledDiv(ref := divRef)

Then the thing that's attempting to render itself within that div is trying to call attachShadow on that div element, only to be told that attachShadow is not a function on that element. A quick search on the web didn't yield a great deal other than make sure the html element supports attachShadow, which div should. Does anyone have any experience with this kind of error or any thoughts on what the issue might be? Many thanks!

mn98
@mn98
@shadaj is the “attachShadow” issue the same or similar?
mn98
@mn98
I confirmed that the attachShadow issue only occurs when using a slinky styled div, it works ok when using a regular slinky html div with a regular css style in the html.
Oleg Pyzhcov
@oleg-py
@shadaj:matrix.org I took a look into that derivation and it seems to be pretty standard TC derivation - is there any specific reason I'm missing as to why Magnolia has been removed?
shadaj
@shadaj:matrix.org
[m]
@oleg-py: at least a couple years ago, Magnolia would perform the actual derivation at runtime (so the macro would just collect metadata), which resulted in a lot of code bloat; so Slinky moved to a custom derivation system that allows the specific TC instances to be created at expansion time (along with a bunch of caching logic), which shaved off a good 100KiB from gzip bundles of a production app
Since Scala 3 is going to be supported in beta mode initially anyways, it could make sense to have Slinky use Magnolia there
Alexander Samsig
@asamsig:matrix.org
[m]
I have been researching the read/write-macro, and the new Mirror-API seems like a great fit, except it doesn't support value classes and default values at the moment.
There is open issues for it, so we can hope they get resolved in the near future.
Alexander Samsig
@asamsig:matrix.org
[m]

I took a tour over the Play-JSON & Magnolia progress and value classes, opaque types, nested sealed traits, default values, are the biggest issues currently with migrating to Scala 3.

I've been experimenting with making Slinky, Scala 3 compatible, but I ran out of time for the time being, most of the work I've done is updating dependencies and splitting code that isn't compatible anymore.

I've barely started to look into the macros, my unfamiliarity with Scala 2&3 macros, made it a bigger endeavor, so not any progress to report.

I have a branch on my on fork here: https://github.com/Asamsig/slinky/tree/scala-3-support

Oleg Pyzhcov
@oleg-py
@asamsig:matrix.org I've made a PR against your fork with some derivation things. It doesn't seem too impossible to make new derivation, but there are cases like recursive case classes I've no idea how to make work, and there are cases where there's nothing out of the box, like non-case AnyVal classes.
Alexander Samsig
@asamsig:matrix.org
[m]
@oleg-py: Awesome!
The basic derivations should be quite straightforward with Mirrors as you've done, the problem is what you say, that they currently don't support, recursive case classes, value classes, default values and such, so for now we won't be able to give parity with Scala 2 Slinky.
Perhaps we can finish up a MVP, with what is supported now, document unsupported things, and have a Beta release or something for Scala 3 😎
Oleg Pyzhcov
@oleg-py
it's possible that value classes and default values can be achieved using custom reflect-macro-generated mirror-like things like I made for unions, though my macro experience ain't that big either
evbo
@evbo

I'm noticing Option[ReactElement] compiles just the same in slinky as ReactElement?

Is that intentional? Seems a little too loose

Just found some old code that was setting a props like someProps = Some(reactElement) even though that props attribute wasn't an Option type it was uncaught. So I removed the Some and it made no difference.
shadaj
@shadaj:matrix.org
[m]
@evbo yeah, this is intentional since React has specific support for optional elements (null in JS land)
evbo
@evbo
gotcha, but fwiw wouldn't it be better on all fronts to require it to be explicitly typed to help when one wants to enforce non null? Could also help with readability, e.g.: val a: ReactElement = Some(Some("but I am not supposed to be an option"))
shadaj
@shadaj:matrix.org
[m]
hmm, yeah that's a tricky design question; so far, Slinky has erred on the side of "if this is supported and meaningful in React, then it should be supported in Scala", so the Option conversion falls under that
evbo
@evbo

all good, this only came up because I am trying to tuck as much logic as possible into the JVM, which boils down to ReactElement.asInstanceOf[SomeCaseClassThatExtendsAnyVal]

So that on the JVM side I at least have the ability of handling the ReactElement objects. But now that I know option counts as a ReactElement I need to rethink my strategy a bit

evbo
@evbo

@shadaj:matrix.org figured out an answer to my question up above

Whenever js Objects don't seem to automatically be read correctly into the case class, for some reason just treating them as a class that extends js.Object appears to work.

Is this intended?

Example:

The notorious react-table has a hook, useTable that returns a ton of stuff, but for example here is a working facade:

@js.native
@JSImport("react-table", JSImport.Default)
object ReactTableLibrary extends js.Object {
  def useTable(props: js.Object, plugins: js.Any*): TableProps = js.native
}

If I use a case class I will get the [object object] is not an instance of TableProps error, forcing me to instead return a js.Object and then dynamically building the case class myself!

val props = useTable(...).asInstanceOf[js.Dynamic]

val typedProps = TableProps(
props.selectDynamic("headerGroups").asInstanceOf[js.Array[HeaderGroup]],
props.selectDynamic("rows").asInstanceOf[js.Array[Row]],
props.selectDynamic("prepareRow").asInstanceOf[js.Function1[Row, Unit]]
)

If instead I define TableProps as a regular class that extends js.Object, no need for gross dynamic selecting, slinky works!

// solution:
class TableProps(
                  val headerGroups: js.Array[HeaderGroup],
                  val rows: js.Array[Row],
                  val prepareRow: js.Function1[Row, Unit]
                ) extends js.Object
I always thought case class was the way to go, sorry if I missed it in the docs somewhere to use class. Just weird cause sometimes case class works fine and then in certain edge cases it doesn't. Is there a reason?
shadaj
@shadaj:matrix.org
[m]
@evbo: ah, yeah so Slinky can only perform automatic case class conversions when the type is part of props, so in this case when you return it from a js.native facade there's no automatic conversion and you get an error; when defining the return type of a js.native method, you'll generally have to use a js.Object trait to define that type
Jason Pickens
@steinybot
Any idea why my cleanup function from useEffect is not being called? I tried explicitly typing it as a js.Function but that didn’t help.
Woops never mind. I didn’t even return it. Tut tut.
Jason Pickens
@steinybot
Damn still not working
Jason Pickens
@steinybot
Ah returning a js.Function doesn’t work as that will cause EffectCallbackReturn.fromAny to be used which makes it undefined
shadaj
@shadaj:matrix.org
[m]
we should probably add an EffectCallbackReturn.fromJSFunction
Jason Pickens
@steinybot
Also is it a bug that useState returns a new SetStateHookCallbackinstance each time? I was using this as a dependency in useEffect. It’s not strictly necessary to pass it as a dependency since it should never change but I prefer to include everything rather than having special rules for certain things.
evbo
@evbo

@shadaj:matrix.org thank you! And one excruciatingly difficult typo that can easily happen with a regular class, is for getting to put val in front of the attribute name.

If you don't do that, no compile-time error but it simply won't be included in the js Object!!

Catching that one kept me busy for a few hours :)

Jason Pickens
@steinybot