diff --git a/Partas.Solid.FablePlugin/Plugin.fs b/Partas.Solid.FablePlugin/Plugin.fs index 07ce43f..9822971 100644 --- a/Partas.Solid.FablePlugin/Plugin.fs +++ b/Partas.Solid.FablePlugin/Plugin.fs @@ -901,7 +901,7 @@ module internal rec AST = | Call( Import({ Selector = "op_BangAt"; Kind = MemberImport(MemberRef({ FullName = "Partas.Solid.Builder" }, _)) }, _, _), { - Args = Lambda(_, Call(callee, _, _, _), _) :: _ + Args = Lambda(_, Call(callee, callInfo, _, _), _) :: _ }, _, range @@ -909,7 +909,15 @@ module internal rec AST = match callee with // Some ident | IdentExpr({ Type = Type.PartasName ctx typeName } as identee) -> - IdentExpr({ identee with Name = typeName |> Utils.trimReservedIdentifiers }) |> Some + match callInfo with + // In the case where the referenced tag is a constructor, then it is a SolidTypeComponent, and we + // actually intend to reference the name of the type. + | CallInfo.Constructor ctx -> + IdentExpr({ identee with Name = typeName |> Utils.trimReservedIdentifiers }) |> Some + // Where the above is not true, the referenced tag is a let binding, and therefore a SolidComponent, + // so we intent to reference the name of the binding. + | _ -> + callee |> Some // prevent import of native tags | Expr.NativeImportedConstructor ctx & Import( @@ -923,9 +931,18 @@ module internal rec AST = | Import( importInfo, typ & Type.PartasName ctx typeName, - range) -> - Import({ importInfo with Selector = typeName }, typ, range) - |> Some + range) as expr-> + // We determine if the imported tag was a constructor. If it was, then it is a SolidTypeComponent, + // and the name of the component will be the name of the type. + match callInfo with + | CallInfo.Constructor ctx -> + Import({ importInfo with Selector = typeName }, typ, range) + |> Some + // If the above is not true, then the tag is a SolidComponent let binding, and the name of the + // component will be the name of the binding. + | _ -> + expr + |> Some | Import({ Kind = UserImport false }, _, _) -> Some callee | _ -> None diff --git a/Partas.Solid.Tests/Partas.Solid.Tests.fsproj b/Partas.Solid.Tests/Partas.Solid.Tests.fsproj index 3340658..1a0bc05 100644 --- a/Partas.Solid.Tests/Partas.Solid.Tests.fsproj +++ b/Partas.Solid.Tests/Partas.Solid.Tests.fsproj @@ -61,6 +61,10 @@ + + + + diff --git a/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.expected b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.expected new file mode 100644 index 0000000..1775b17 --- /dev/null +++ b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.expected @@ -0,0 +1,26 @@ +import { splitProps, mergeProps } from "solid-js"; +import { FakeImportedTag } from "fakeLibrary"; +import { ModuleTag } from "./SolidComponentAsTagValuesTypes.fs.jsx"; + +export function CustomTag(props) { + props = mergeProps({ + icon: button, + }, props); + const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["icon"]); + return
+ + + + + +
; +} + +export function Rock() { + const Comp = FakeImportedTag; + return + + ; +} diff --git a/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fs b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fs new file mode 100644 index 0000000..6788986 --- /dev/null +++ b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fs @@ -0,0 +1,28 @@ +module Partas.Solid.Tests.SolidCases.SolidComponentAsTagValues.SolidComponentAsTagValues + +open Partas.Solid.Tests.SolidCases.SolidComponentAsTagValues.SolidComponentAsTagValuesTypes +open Partas.Solid +open Fable.Core +open Fable.Core.JsInterop + +[] +type CustomTag() = + interface RegularNode + [] + member val icon: TagValue = unbox null with get,set + [] + member props.constructor = + props.icon <- !@button + div() { + props.icon % {| class' = "KeyVal" |} + props.icon % {| class' = "KeyVal2" |} + props.icon % div(class' = "constructor") { button() { "internal" } } + + } + +[] +let Rock () = + let Comp = !@Imported + CustomTag(icon = unbox !@a) { + Comp % Imported(other = !@ModuleTag ) + } diff --git a/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fsproj b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fsproj new file mode 100644 index 0000000..bffb9ed --- /dev/null +++ b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fsproj @@ -0,0 +1,17 @@ + + + + Exe + net9.0 + + + + + + + + + + + + diff --git a/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValuesTypes.fs b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValuesTypes.fs new file mode 100644 index 0000000..f8cd7a2 --- /dev/null +++ b/Partas.Solid.Tests/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValuesTypes.fs @@ -0,0 +1,16 @@ +module Partas.Solid.Tests.SolidCases.SolidComponentAsTagValues.SolidComponentAsTagValuesTypes + +open Partas.Solid +open Fable.Core + +#nowarn 64 + +[] +let ModuleTag() = + div() + +[] +type Imported() = + interface RegularNode + [] + member val other: TagValue = jsNative with get,set diff --git a/Partas.Solid.Tests/SolidTests.fs b/Partas.Solid.Tests/SolidTests.fs index c707696..fc7d3ab 100644 --- a/Partas.Solid.Tests/SolidTests.fs +++ b/Partas.Solid.Tests/SolidTests.fs @@ -51,6 +51,10 @@ let ``Field getters and records are transformed`` () = let ``Tags can be used as values`` () = runSolidCase "TagsAsValuesSimple" +[] +let ``SolidComponents can be used as TagValues`` () = + runSolidCase "SolidComponentAsTagValues" + [] let ``FieldGets like props.words.Length are transformed`` () = runSolidCase "FieldGetExpressionsTransformed" @@ -69,4 +73,4 @@ let ``CssStyle definitions compile correct output`` () = [] let ``ChildLambdaProvider interfaces`` () = - runSolidCase "ChildLambdaProvider" \ No newline at end of file + runSolidCase "ChildLambdaProvider" diff --git a/Partas.Solid/Builder.fs b/Partas.Solid/Builder.fs index 6a8a948..cdf8671 100644 --- a/Partas.Solid/Builder.fs +++ b/Partas.Solid/Builder.fs @@ -124,7 +124,7 @@ module Builder = /// let tag = !@div /// [] - type TagValue(tag: unit -> #HtmlElement) = + type TagValue(tag: FSharpFunc<_,#HtmlElement>) = /// /// Directs the plugin to build the call site as a Tag /// in JSX. @@ -178,7 +178,7 @@ module Builder = /// let tag = !@div /// [] - let (!@) (this: unit -> 'T) = TagValue(unbox this) + let (!@) (this: FSharpFunc<_,#HtmlElement>) = TagValue(unbox this) /// Alias used in the provided builder [] diff --git a/ScratchTests/Test.fs b/ScratchTests/Test.fs deleted file mode 100644 index 7e6d3e0..0000000 --- a/ScratchTests/Test.fs +++ /dev/null @@ -1,17 +0,0 @@ -module Partas.Solid.Test.Burger - -open Partas.Solid -open Partas.Solid.Test -open Fable.Core - - -type [] TagWithTextChild() = - inherit RegularNode() - [] - member props.typeDef = - div(class' = "boobs") { - "textabove" - div() - "textbelow" - } - \ No newline at end of file