Partas.Solid
0.2.2
Previous versions have missing, or incorrect transformations in uncommon but vital use cases.
See the version list below for details.
dotnet add package Partas.Solid --version 0.2.2
NuGet\Install-Package Partas.Solid -Version 0.2.2
<PackageReference Include="Partas.Solid" Version="0.2.2" />
<PackageVersion Include="Partas.Solid" Version="0.2.2" />
<PackageReference Include="Partas.Solid" />
paket add Partas.Solid --version 0.2.2
#r "nuget: Partas.Solid, 0.2.2"
#addin nuget:?package=Partas.Solid&version=0.2.2
#tool nuget:?package=Partas.Solid&version=0.2.2
Partas.Solid
[!WARNING] This is not compatible with Fable 4.0, as the Plugin is not detected correctly.
Use the latest 5.0 alpha, or wait for full release.
[!IMPORTANT] This is an opinionated fork of Oxpecker.Solid that enables experimental behaviours and patterns which I use in personal projects.
Until such a time as these types of behaviours/patterns are sought out by users, the behaviours will not be supported on the mainstream.
For this reason, I publish this as a means of allowing users to experiment or observe the patterns enabled and submit requests for it to be considered in the mainline.
Features
Reduce undefined behaviour
Hugely opinionated, but I feel that reducing all transformation to a few pathways which expressions must all traverse simplifies the cognitive load for developing the plugin. The bulk of the code is boiler plate reduction for Expr pattern matches.
I feel this iteration has less specific pattern matchers, which prevents what might some deem as undocumented behaviour.
As an example, currently Oxpecker would perform the following conversion:
let mutable show = true
[<SolidComponent>]
let Button () =
let this = button() {
"some boiler plate"
}
div(class'="MyButton") {
if show then this else ()
}
export let show = createAtom(true);
export function Button() {
return <button>
some boiler plate
</button>;
}
As opposed to the proposed iteration:
export let show = createAtom(true);
export function Button() {
const this$ = <button>
some boiler plate
</button>;
return <div class="MyButton">
{show() ? this$ : undefined}
</div>;
}
Using ternary conditional expressions in solid-js works, although there is
also the <Match>
or <Show>
tags.
Custom Tags & Components in Oxpecker Syntax
Currently, Oxpecker doesn't support the ability to create components and then use them in the Oxpecker style.
Naturally, this is because a functional approach would not use the DSL to construct final pages, and use functions instead. But creating a permissive and flexible component library wouldn't work in this manner without being extremely verbose.
As an alternative, the current iteration provides an extra attribute which can be applied to members of your type definition for the tag using props
as the self identifier. The self identifier, props, allows type safe access to your defined properties which can be set in Oxpecker style.
Any accesses to your properties are automatically split, and you can spread whatever other properties into a tag to allow prop drilling, or to integrate with other component libraries that might use providers etc.
As an added benefit, there is sugar for setting the defaults of any property using <-
.
// -- Program.fs
type [<Erase>] CustomTag() =
inherit RegularNode()
[<SolidTypeComponent>]
member private props.typeDef =
props.class' <- "DefaultClass" // setting properties will set the 'default'
div(class' = props.class') {
button().spread(props)
}
function CustomTag(props) {
props = mergeProps({
class: "DefaultClass",
}, props);
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <div class={PARTAS_LOCAL.class}>
<button {...PARTAS_OTHERS} bool:n$={false} />
</div>;
}
[!NOTE] There is a pull in discussion on Fable that will prevent the need for the noop
bool:n$={false}
after the spread.
You can use those tags like any other import from other files, and from the standard attribute SolidComponent
:
// -- Test.fs
open Program
[<SolidComponent>]
let SomeTag () =
let this = button() { "some boiler plate" }
CustomTag(class'="MyButton") {
if show then this else ()
}
import { createAtom } from "./fable_modules/fable-library-js.5.0.0-alpha.11/Util.js";
import { CustomTag } from "./Program.fs.jsx";
export let show = createAtom(true);
export function SomeTag() {
const this$ = <button>
some boiler plate
</button>;
return <CustomTag class="MyButton">
{show() ? this$ : undefined}
</CustomTag>;
}
You can set those defaults in a deeply nested tree where you actually make use of them. As an example of where/what undefined behaviour looks like currently, I've included this example despite it producing unsatisfactory output. This would be the first time I've actually tested this capability!
type [<Erase>] CustomTag() =
inherit RegularNode()
[<SolidTypeComponent>]
member private props.typeDef =
div(){
div(class' = props.class') {
button().spread(props)
props.class' <- "ProximalDefaultDefinition"
}
}
function CustomTag(props) {
props = mergeProps({
class: "ProximalDefaultDefinition",
}, props);
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <div>
<div class={PARTAS_LOCAL.class}>
<button {...PARTAS_OTHERS} bool:n$={false} />
{(value) => {
}}
</div>
</div>;
}
To prevent undefined behaviour further, I can easily add an error when a property is set twice, for safety.
Conclusion
If you like this kind of thing DSL, let me know!
I'll be developing a component library that will make heavy usage of the type definition feature to allow you to copy paste and change what you want.
Install
dotnet add package Partas.Solid
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net9.0
- Fable.Browser.Dom (>= 2.18.1)
- Fable.Core (>= 4.4.0)
- FSharp.Core (>= 9.0.100)
- Partas.Solid.FablePlugin (>= 0.2.2)
NuGet packages (6)
Showing the top 5 NuGet packages that depend on Partas.Solid:
Package | Downloads |
---|---|
Partas.Solid.TanStack.Table
Bindings for TanStack.Table for Partas.Solid |
|
Partas.Solid.Corvu
Bindings for Solid-Corvu in Oxpecker.Solid Style compatible with Partas.Solid |
|
Partas.Solid.Cmdk
Bindings for Solid-Cmdk in Oxpecker.Solid Style compatible with Partas.Solid |
|
Partas.Solid.Kobalte
Bindings for Solid-Kobalte in Oxpecker.Solid Style compatible with Partas.Solid |
|
Partas.Solid.Primitives
Bindings for different packages in Solid-Primitives in Oxpecker.Solid Style compatible with Partas.Solid |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
0.2.27 | 151 | 3/22/2025 | |
0.2.26 | 66 | 3/22/2025 | |
0.2.25 | 59 | 3/22/2025 | |
0.2.24 | 88 | 3/21/2025 | |
0.2.23 | 112 | 3/21/2025 | |
0.2.22 | 171 | 3/20/2025 | |
0.2.21 | 130 | 3/20/2025 | |
0.2.20 | 133 | 3/20/2025 | |
0.2.19 | 135 | 3/19/2025 | |
0.2.18 | 124 | 3/16/2025 | |
0.2.17 | 123 | 3/16/2025 | |
0.2.16 | 105 | 3/14/2025 | |
0.2.15 | 124 | 3/14/2025 | |
0.2.14 | 143 | 3/12/2025 | |
0.2.13 | 154 | 3/12/2025 | |
0.2.12 | 148 | 3/12/2025 | |
0.2.11 | 150 | 3/11/2025 | |
0.2.10 | 167 | 3/9/2025 | |
0.2.9 | 229 | 3/9/2025 | |
0.2.8 | 237 | 3/9/2025 | |
0.2.7 | 235 | 3/9/2025 | |
0.2.6 | 260 | 3/8/2025 | |
0.2.5 | 278 | 3/7/2025 | |
0.2.4 | 279 | 3/7/2025 | |
0.2.3 | 262 | 3/7/2025 | |
0.2.2 | 258 | 3/7/2025 | |
0.2.1 | 270 | 3/7/2025 | |
0.2.0 | 280 | 3/6/2025 | |
0.1.0 | 180 | 3/1/2025 |
Transforms expressions inside anon records to integrate with cva usage