Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions examples/hono-jsx-ts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# prod
dist/

# dev
.hono/
.wrangler/
.yarn/
!.yarn/releases
.vscode/*
!.vscode/launch.json
!.vscode/*.code-snippets
.idea/workspace.xml
.idea/usage.statistics.xml
.idea/shelf

# deps
node_modules/

# env
.env
.env.production
.dev.vars

# logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

# misc
.DS_Store
3 changes: 3 additions & 0 deletions examples/hono-jsx-ts/app/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createClient } from "honox/client"

createClient()
8 changes: 8 additions & 0 deletions examples/hono-jsx-ts/app/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type {} from "hono"

declare module "hono" {
interface Env {
Variables: {}
Bindings: {}
}
}
13 changes: 13 additions & 0 deletions examples/hono-jsx-ts/app/islands/counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useState } from "hono/jsx"

export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p class="py-2 text-2xl">{count}</p>
<button class="px-4 py-2 bg-orange-400 text-white rounded cursor-pointer" onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
)
}
8 changes: 8 additions & 0 deletions examples/hono-jsx-ts/app/routes/_404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { NotFoundHandler } from "hono"

const handler: NotFoundHandler = (c) => {
c.status(404)
return c.render("404 Not Found")
}

export default handler
12 changes: 12 additions & 0 deletions examples/hono-jsx-ts/app/routes/_error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { ErrorHandler } from "hono"

const handler: ErrorHandler = (e, c) => {
if ("getResponse" in e) {
return e.getResponse()
}
console.error(e.message)
c.status(500)
return c.render("Internal Server Error")
}

export default handler
17 changes: 17 additions & 0 deletions examples/hono-jsx-ts/app/routes/_renderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { jsxRenderer } from "hono/jsx-renderer"
import { Link, Script } from "honox/server"

export default jsxRenderer(({ children }) => {
return (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<Link href="/app/style.css" rel="stylesheet" />
<Script src="/app/client.ts" async />
</head>
<body>{children}</body>
</html>
)
})
49 changes: 49 additions & 0 deletions examples/hono-jsx-ts/app/routes/accordion/$Accordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as accordion from "@zag-js/accordion"
import { normalizeProps, useMachine } from "@zag-js/hono-jsx"
import { useId } from "hono/jsx"

const items = [
{
title: "Watercraft",
desc: "Yacht, Boats and Dinghies",
content: "Sample accordion content",
},
{
title: "Automobiles",
desc: "Cars, Trucks and Vans",
content: "Sample accordion content",
},
{
title: "Aircraft",
desc: "Airplanes, Helicopters and Rockets",
content: "Sample accordion content",
},
]

type AccordionProps = Omit<accordion.Props, "id">

export default function Accordion(props: AccordionProps) {
const service = useMachine(accordion.machine, {
id: useId(),
defaultValue: ["Aircraft"],
...props,
})

const api = accordion.connect(service, normalizeProps)

return (
<div {...api.getRootProps()}>
{items.map((item) => (
<div key={item.title} {...api.getItemProps({ value: item.title })}>
<h3>
<button {...api.getItemTriggerProps({ value: item.title })}>
<div>{item.title}</div>
<div>{item.desc}</div>
</button>
</h3>
<div {...api.getItemContentProps({ value: item.title })}>{item.content}</div>
</div>
))}
</div>
)
}
12 changes: 12 additions & 0 deletions examples/hono-jsx-ts/app/routes/accordion/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createRoute } from "honox/factory"
import Accordion from "./$Accordion"

export default createRoute((c) => {
return c.render(
<div class="py-8 text-center">
<title>Accordion</title>
<h1 class="text-3xl font-bold">Accordion</h1>
<Accordion collapsible={true} multiple={false} />
</div>,
)
})
38 changes: 38 additions & 0 deletions examples/hono-jsx-ts/app/routes/avatar/$Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as avatar from "@zag-js/avatar"
import { normalizeProps, useMachine } from "@zag-js/hono-jsx"
import { useId } from "hono/jsx"

interface AvatarProps extends Omit<avatar.Props, "id"> {
src: string
name: string
}

export default function Avatar(props: AvatarProps) {
const [avatarProps, restProps] = avatar.splitProps(props)
const { src, name } = restProps

const service = useMachine(avatar.machine, {
id: useId(),
...avatarProps,
})

const api = avatar.connect(service, normalizeProps)

const initial = name
.split(" ")
.map((s) => s[0])
.join("")

return (
<>
<main className="avatar">
<div {...api.getRootProps()}>
<div {...api.getFallbackProps()}>
<div>{initial}</div>
</div>
<img alt={name} referrerPolicy="no-referrer" src={src} {...api.getImageProps()} />
</div>
</main>
</>
)
}
17 changes: 17 additions & 0 deletions examples/hono-jsx-ts/app/routes/avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createRoute } from "honox/factory"
import Avatar from "./$Avatar"

export default createRoute((c) => {
return c.render(
<div class="py-8 text-center">
<title>Avatar</title>
<h1 class="text-3xl font-bold">Avatar</h1>
<Avatar
name={"Segun Adebayo"}
src={
"https://static.wikia.nocookie.net/naruto/images/d/d6/Naruto_Part_I.png/revision/latest/scale-to-width-down/300?cb=20210223094656"
}
/>
</div>,
)
})
35 changes: 35 additions & 0 deletions examples/hono-jsx-ts/app/routes/checkbox/$Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as checkbox from "@zag-js/checkbox"
import { normalizeProps, useMachine } from "@zag-js/hono-jsx"
import { useId } from "hono/jsx"

interface CheckboxProps extends Omit<checkbox.Props, "id"> {}

export default function Checkbox(props: CheckboxProps) {
const service = useMachine(checkbox.machine, {
id: useId(),
...props,
})

const api = checkbox.connect(service, normalizeProps)

return (
<div>
<label {...api.getRootProps()}>
<span {...api.getLabelProps()}>Checkbox Input</span>
<input data-peer {...api.getHiddenInputProps()} />
<div {...api.getControlProps()}>
{api.checkedState === true && (
<svg viewBox="0 0 24 24" fill="currentColor" transform="scale(0.7)">
<path d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z" />
</svg>
)}
{api.checkedState === "indeterminate" && (
<svg viewBox="0 0 24 24" stroke="currentColor" strokeWidth="4">
<line x1="21" x2="3" y1="12" y2="12" />
</svg>
)}
</div>
</label>
</div>
)
}
12 changes: 12 additions & 0 deletions examples/hono-jsx-ts/app/routes/checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createRoute } from "honox/factory"
import Checkbox from "./$Checkbox"

export default createRoute((c) => {
return c.render(
<div class="py-8 text-center">
<title>Checkbox</title>
<h1 class="text-3xl font-bold">Checkbox</h1>
<Checkbox disabled={false} invalid={false} />
</div>,
)
})
114 changes: 114 additions & 0 deletions examples/hono-jsx-ts/app/routes/combobox/$Combobox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import * as combobox from "@zag-js/combobox"
import { Portal, mergeProps, normalizeProps, useMachine } from "@zag-js/hono-jsx"
import { useId, useMemo, useState } from "hono/jsx"
import { createFilter } from "@zag-js/i18n-utils"

interface ComboboxProps extends Omit<combobox.Props, "id" | "collection"> {}

export default function Combobox(props: ComboboxProps) {
const [options, setOptions] = useState(comboboxData)

const filter = createFilter({ sensitivity: "base" })

const collection = useMemo(
() =>
combobox.collection({
items: options,
itemToValue: (item) => item.code,
itemToString: (item) => item.label,
}),
[options],
)

const service = useMachine(combobox.machine, {
id: useId(),
collection,
onInputValueChange({ inputValue }) {
const filtered = comboboxData.filter((item) => filter.contains(item.label, inputValue))
setOptions(filtered.length > 0 ? filtered : comboboxData)
},
placeholder: "Type or select country",
...props,
})

const api = combobox.connect(service, normalizeProps)

const triggerProps = mergeProps(api.getTriggerProps(), {
onClick() {
setOptions(comboboxData)
},
})

return (
<div>
<div {...api.getRootProps()}>
<label {...api.getLabelProps()}>Nationality</label>
<div {...api.getControlProps()}>
<input {...api.getInputProps()} />
<button {...triggerProps}>
<CaretIcon />
</button>
</div>
</div>
<Portal>
<div {...api.getPositionerProps()}>
{options.length > 0 && (
<ul {...api.getContentProps()}>
{options.map((item, index) => (
<li key={`${item.code}:${index}`} {...api.getItemProps({ item })}>
{item.label}
</li>
))}
</ul>
)}
</div>
</Portal>
</div>
)
}

const comboboxData = [
{ label: "Zambia", code: "ZA" },
{ label: "Benin", code: "BN" },
{ label: "Canada", code: "CA" },
{ label: "United States", code: "US" },
{ label: "Japan", code: "JP" },
{ label: "Nigeria", code: "NG" },
{ label: "Albania", code: "AL" },
{ label: "Algeria", code: "DZ" },
{ label: "American Samoa", code: "AS" },
{ label: "Andorra", code: "AD" },
{ label: "Angola", code: "AO" },
{ label: "Anguilla", code: "AI" },
{ label: "Antarctica", code: "AQ" },
{ label: "Australia", code: "AU" },
{ label: "Austria", code: "AT" },
{ label: "Azerbaijan", code: "AZ" },
{ label: "Bahamas", code: "BS" },
{ label: "Bahrain", code: "BH" },
{ label: "Madagascar", code: "MG" },
{ label: "Malawi", code: "MW" },
{ label: "Malaysia", code: "MY" },
{ label: "Maldives", code: "MV" },
{ label: "Mali", code: "ML" },
{ label: "Malta", code: "MT" },
{ label: "Togo", code: "TG" },
{ label: "Tokelau", code: "TK" },
{ label: "Tonga", code: "TO" },
{ label: "Trinidad and Tobago", code: "TT" },
{ label: "Tunisia", code: "TN" },
]

const CaretIcon = () => (
<svg
stroke="currentColor"
fill="currentColor"
strokeWidth="0"
viewBox="0 0 1024 1024"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"></path>
</svg>
)
Loading