lenards / elm-ui-patternfly

An exploration of defining Pattern Fly design in elm-ui
BSD 3-Clause "New" or "Revised" License
7 stars 2 forks source link

Explore How to Expose "Ports" in the Library ... #1

Open lenards opened 3 years ago

lenards commented 3 years ago

There was a discussion on Elm Slack around 2021-01-24 about how to provide an interface to "hook into" a library via Ports since you cannot include ports in a library.

I've been curious about this, and wasn't really sure how to address this - but I imagined the Elm community had faced it in some way.

The thread is captured below in Details.

I'm anonymized the names because I do not know if copying and persisting transcripts from Elm Slack is permissible within Elm Slack community code or etiquette. ``` person1 Jan 24th at 6:47 PM update : (Value -> Cmd msg) -> List Node -> Cmd msg resume : (Value -> Cmd msg) -> Cmd msg suspend : (Value -> Cmd msg) -> Cmd msg So packages can't define ports, we know this. It feels a bit clunky having to pass the port in manually. Does anyone have any nice solutions? Are we all just wrapping Programs person2 2 days ago It's a nasty problem. I went with this solution in elm-mapbox. The README says: Next, optionally, setup a ports module. The best way to do this is to to copy this file into your project. I usually name it Map/Cmd.elm This will allow you to easily use the commands to control parts of your map interactions imperatively - for example you can command your map to fly to a particular location. To enable that, the library ships with a module called Mapbox.Cmd.Template, which you would wrap in your own module. person3 2 days ago I document the port types, and put instructions in the README around how to set it up. For example, https://package.elm-lang.org/packages/the-sett/elm-localstorage/latest/, there is code in a Gist that users can cut and paste. person1 2 days ago make : GetItemPort msg -> SetItemPort msg -> ClearPort msg -> ListKeysPort msg -> String -> LocalStorage msg ah and then you wrap them all up in a type/value. person3 2 days ago How would you do it with a wrapped Program? Define a new program type with a constructor that requires the port implementations to plug into it? I guess that is helpful for the case where someone wants to build a program based mainly around your ports package. person3 2 days ago Yeah bundled them all up into LocalStorage which acts as a kind of handler reference that you must use everywhere in the API. person1 2 days ago I could do that here, those functions already exist in a WebAudio.Context module, and there's already a Context type that needs to be constructed. person3 2 days ago Neat to have everything in the Context. person3 2 days ago I see you have a port for all the operations, thoughts on that vs a single port and handling the different operations in js? (edited) person3 1 day ago Yes, I didn't like the 2 ports approach so much. If you do that you have to tag each command that goes through the port, so you can switch on them on the other side. Just seems like an extra complication over just having one port per operation. I think both approaches work just fine though. person3 1 day ago miniBill took things to extremes and created a whole 2 port framework that does loads of stuff. The disadvantage of that is that when I just wanted local storage, I had to take his whole framework. Part of the reason I forked his local storage stuff. So I prefer my ports smaller scale, and one per job. (edited) ``` `miniBill` is referring to https://github.com/miniBill
lenards commented 3 years ago

I failed to capture the "why" I was looking to use Ports with PF4. It was to implement their Clipboard Copy component: