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.Plugin/Compiled/Partas.Solid.Tests.Plugin.Compiled.fsproj b/Partas.Solid.Tests.Plugin/Compiled/Partas.Solid.Tests.Plugin.Compiled.fsproj index d6cbeb1..bfb7cc3 100644 --- a/Partas.Solid.Tests.Plugin/Compiled/Partas.Solid.Tests.Plugin.Compiled.fsproj +++ b/Partas.Solid.Tests.Plugin/Compiled/Partas.Solid.Tests.Plugin.Compiled.fsproj @@ -88,6 +88,9 @@ + + + diff --git a/Partas.Solid.Tests.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.expected b/Partas.Solid.Tests.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.expected new file mode 100644 index 0000000..1775b17 --- /dev/null +++ b/Partas.Solid.Tests.Plugin/Compiled/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.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fs b/Partas.Solid.Tests.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fs new file mode 100644 index 0000000..13e45c2 --- /dev/null +++ b/Partas.Solid.Tests.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValues.fs @@ -0,0 +1,29 @@ +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.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValuesTypes.fs b/Partas.Solid.Tests.Plugin/Compiled/SolidCases/SolidComponentAsTagValues/SolidComponentAsTagValuesTypes.fs new file mode 100644 index 0000000..0cd50e6 --- /dev/null +++ b/Partas.Solid.Tests.Plugin/Compiled/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.Plugin/Tests.fs b/Partas.Solid.Tests.Plugin/Tests.fs index bef6d53..be30678 100644 --- a/Partas.Solid.Tests.Plugin/Tests.fs +++ b/Partas.Solid.Tests.Plugin/Tests.fs @@ -90,7 +90,9 @@ let SolidCases = "CssStyles" |> runSolidCase "CssStyle definitions compiles correct output" "ChildLambdaProvider" - |> runSolidCase "ChildLambdaProvider interfaces" ] + |> runSolidCase "ChildLambdaProvider interfaces" + "SolidComponentAsTagValues" + |> runSolidCase "SolidComponent let bindings as TagValues" ] [] let AttributeCases = diff --git a/Partas.Solid/Builder.fs b/Partas.Solid/Builder.fs index 7640453..edd2c34 100644 --- a/Partas.Solid/Builder.fs +++ b/Partas.Solid/Builder.fs @@ -38,6 +38,7 @@ module Builder = type VoidNode = inherit HtmlTag + [] type IChildLambdaProvider = inherit HtmlElement @@ -142,7 +143,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. @@ -200,7 +201,7 @@ module Builder = /// let tag = !@div /// [] - let (!@) (this: unit -> 'T) = + let (!@) (this: FSharpFunc<_, #HtmlElement>) = TagValue (unbox this) /// Alias used in the provided builder