Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Unable to import Soild's html function in Solid Start app #1618

Closed
2 tasks done
trusktr opened this issue Sep 1, 2024 · 5 comments
Closed
2 tasks done

[Bug]: Unable to import Soild's html function in Solid Start app #1618

trusktr opened this issue Sep 1, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@trusktr
Copy link

trusktr commented Sep 1, 2024

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

More details here:

solidjs/solid#1984

Expected behavior 🤔

All of Solid's packages, including solid-js should be importable in Solid Start.

Steps to reproduce 🕹

Steps:

  1. npm create solid and follow steps to create a Solid app
  2. Add import html from 'solid-js/html' to any JS or TS file.
  3. Try to run the app and see the error

Context 🔦

Some components, for example 3rd party components, might be importing Solid's html. It would be great for a Solid app with SSR enabled to not have an issue importing such code (there will be more problems to wrangle after importing such as running certain components only on the client, but that's a next step after first getting imports working).

Fixed by

Your environment 🌎

No response

@trusktr trusktr added the bug Something isn't working label Sep 1, 2024
@trusktr trusktr changed the title [Bug]: Uable to import Soild's html function in Solid Start app [Bug]: Unable to import Soild's html function in Solid Start app Sep 1, 2024
@trusktr
Copy link
Author

trusktr commented Sep 1, 2024

@trusktr
Copy link
Author

trusktr commented Sep 1, 2024

I've confirmed after linking modified solid-js including this change into a Solid Start app that I'm able to progress towards normal import statements.

Even if I'm not calling html on the server side, the app is a lot cleaner being able to hoist import statements out of components or conditional top-level awaits.

@trusktr
Copy link
Author

trusktr commented Sep 1, 2024

Having normal import statements makes things really easy in VS Code too, for example VS Code will autocomplete import statements for anything that you need to import, which is super convenient.

For example write this code (with | representing the cursor location):

createEff|

and VS Code will propose to import createEffect from solid-js, etc. So it will be great for all APIs to be conveniently importable.

The html export from solid-js/html is not currently named, so VS Code will not autocomplete the import for html. Fix for that here:

VS Code will not automatically add await import() expressions, so when someone autocompletes an import statement, it'll go to the top of the file, then they have to manually move that into their conditional or onMount.

@trusktr
Copy link
Author

trusktr commented Sep 1, 2024

Oh my goodness.... YES!

ryansolid/dom-expressions#345 cleans up my Solid Start modules that import lume.

For example I had this ugly code,

ugly code

import {batch, createSignal, onCleanup, onMount} from 'solid-js'
...normal imports...

export type TiltCardAttributes = Element3DAttributes | 'rotationAmount' | ...

// Solid Start import issue: https://github.com/solidjs/solid-start/issues/1614
if (globalThis.window?.document) await defineElement()

async function defineElement() {
	const {default: html} = await import('solid-js/html')
	const {Element3D, Motor, stringAttribute, numberAttribute, booleanAttribute} = await import('lume')
	const {autoDefineElements} = await import('lume/dist/LumeConfig.js')

	return @element('lume-tilt-card', autoDefineElements)
	class TiltCard extends Element3D {
		@numberAttribute rotationAmount = 12
		..etc..

		override template = () => {
			let plane: Element3D
			const state = createMutable({...})
			...

			return html`
				<lume-rounded-rectangle
					ref=${(e: Element3D) => (plane = e)}
					...
				> ... </lume-rounded-rectangle>

			`
		}

	}
}

// Temporary hack type to get around the async defineElement() workaround
type TiltCardCtor = Awaited<ReturnType<typeof defineElement>>
export type TiltCard = InstanceType<TiltCardCtor>

declare module 'solid-js' {
	namespace JSX {
		interface IntrinsicElements {
			'lume-tilt-card': ElementAttributes<TiltCard, TiltCardAttributes>
		}
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'lume-tilt-card': TiltCard
	}
}

Which as you can imagine, gets worse when trying to define more than one custom element in a single file (with JSX types for type checking in Solid components), for example:

even worse code

// ...normal imports...

export type ScrollerAttributes = Element3DAttributes | 'scrollX' | 'scrollY' | ...

export type ScrollItemAttributes = Element3DAttributes | 'skip'

if (globalThis.window?.document) await defineElement()

async function defineElement() {
	const {default: html} = await import('solid-js/html')
	const {Element3D, ScrollFling, booleanAttribute} = await import('lume')
	const {autoDefineElements} = await import('lume/dist/LumeConfig.js')

	@element('lume-scroll-item', autoDefineElements)
	class ScrollItem extends Element3D {
		@booleanAttribute skip = false
	}

	@element('lume-scroller', autoDefineElements)
	class Scroller extends Element3D {
		override readonly hasShadow = true
		
		@booleanAttribute scrollX = true
		@booleanAttribute scrollY = true
		
		...

		override template = () => html`
			<lume-element3d size-mode="p p" size="1 1" id="scrollarea">
				...
			</lume-element3d>
		`
	}

	return [Scroller, ScrollItem] as const // <----------------------------- HACK
}

type ScrollerCtor = Awaited<ReturnType<typeof defineElement>>[0] // <----------------------------- HACK
export type Scroller = InstanceType<ScrollerCtor>

declare module 'solid-js' {
	namespace JSX {
		interface IntrinsicElements {
			'lume-scroller': ElementAttributes<Scroller, ScrollerAttributes>
		}
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'lume-scroller': Scroller
	}
}

type ScrollItemCtor = Awaited<ReturnType<typeof defineElement>>[1] // <----------------------------- HACK
export type ScrollItem = InstanceType<ScrollItemCtor>

declare module 'solid-js' {
	namespace JSX {
		interface IntrinsicElements {
			'lume-scroll-item': ElementAttributes<ScrollItem, ScrollItemAttributes>
		}
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'lume-scroll-item': ScrollItem
	}
}

The code is now much cleaner with normal imports thanks to ryansolid/dom-expressions#345:

clean code

// ...normal imports...
import html from 'solid-js/html'
import {element, type ElementAttributes, booleanAttribute} from '@lume/element'
import {type Element3DAttributes, Element3D, ScrollFling} from 'lume'
import {autoDefineElements} from 'lume/dist/LumeConfig.js'

export type ScrollItemAttributes = Element3DAttributes | 'skip'

@element('lume-scroll-item', autoDefineElements)
class ScrollItem extends Element3D {
	@booleanAttribute skip = false
}

declare module 'solid-js' {
	namespace JSX {
		interface IntrinsicElements {
			'lume-scroll-item': ElementAttributes<ScrollItem, ScrollItemAttributes>
		}
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'lume-scroll-item': ScrollItem
	}
}

export type ScrollerAttributes = Element3DAttributes | 'scrollX' | 'scrollY' | ...

@element('lume-scroller', autoDefineElements)
class Scroller extends Element3D {
	override readonly hasShadow = true
	
	@booleanAttribute scrollX = true
	@booleanAttribute scrollY = true
	
	...

	override template = () => html`
		<lume-element3d size-mode="p p" size="1 1" id="scrollarea">
			...
		</lume-element3d>
	`
}

declare module 'solid-js' {
	namespace JSX {
		interface IntrinsicElements {
			'lume-scroller': ElementAttributes<Scroller, ScrollerAttributes>
		}
	}
}

declare global {
	interface HTMLElementTagNameMap {
		'lume-scroller': Scroller
	}
}

@ryansolid
Copy link
Member

This should be fixed as of 1.9 now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants