DEV Community

Thomas Reggi
Thomas Reggi

Posted on

HTMX + JSX prototype syntax for server side html.

// a HTMX approach with JSX?
import { Fragment, JSX } from "preact";
import { nanoid } from 'nanoid'

interface Options {
  path: string
}

const routes = []

class HTMX_IN_JSX {
  id: string
  constructor(
    public Component: (props: any) => any, 
    public opt?: Options
  ) {
    this.id = nanoid()
    routes.push(this)
  }
  get path () {
    if (this.opt?.path) return this.opt.path
    throw new Error('Href for component not available')
  }
  get href () {
    return this.path
  }
  get target () {
    return {"hx-target": `#${this.id}`}
  }
  get put () {
    return {"hx-put": this.path}
  }
  get get () {
    return {"hx-get": this.path}
  }
  WrapId () {
    return (props: any) => (
      <span id={this.id}>
        <this.Component {...props}/>
      </span>
    )
  }
  Anchor (props: any): JSX.Element {
    return <a href={this.href}>{props.children}</a>
  }
  AnchorBoost (props: any): JSX.Element {
    return <a href={this.href} hx-boost="true">{props.children}</a>
  }
}

const component = (x: (props: any) => any, opt?: Options): ((props: any) => any) & HTMX_IN_JSX => {
  const instance = new HTMX_IN_JSX(x, opt)
  const ex = instance.WrapId()
  return Object.assign(ex, instance)
}

const Greeting = component(() => {
  return (
    <div>
      <h1>hello</h1>
    </div>
  )
}, {
  path: '/greeting',
})

const Placeholder = component(() => {})

const Page = component(() => {
  return (
    <div>
      <Placeholder/>
      <Greeting.Anchor>Navigates to anchor</Greeting.Anchor>
      <Greeting.AnchorBoost>Fetches anchor page and swaps dom</Greeting.AnchorBoost>
      <a href={Greeting.href}>Simple link to greeting page</a>
      <div {...{...Greeting.put, ...Placeholder.target}}>put to greeting</div>
    </div>
  )
}, {
  path: '/',
})


serve(routes)

Enter fullscreen mode Exit fullscreen mode

Top comments (0)