Skip to content

Commit

Permalink
Add preact example
Browse files Browse the repository at this point in the history
I think given webreflection's decision to abandon supporting hooks in uhooks, and preact generally being more conventional in practice, switching the primary happy path over to preact would make top-bun more palatable to people.
The api in uhtml is superior, and closer to the reality of the DOM, but preact has thus far been closer to react and quicker to ship support for signals and retaining local component state features.
Seems like a more stable long term bet.
  • Loading branch information
bcomnes committed Sep 28, 2024
1 parent 3a99703 commit 72ce635
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 8 deletions.
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ updates:
directory: "/examples/nested-dest/"
schedule:
interval: "daily"
- package-ecosystem: "npm"
directory: "/examples/preact/"
schedule:
interval: "daily"
- package-ecosystem: "npm"
directory: "/examples/string-layouts/"
schedule:
Expand Down
25 changes: 25 additions & 0 deletions examples/preact/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@top-bun/preact-example",
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "npm run watch",
"build": "npm run clean && top-bun",
"clean": "rm -rf public && mkdir -p public",
"watch": "npm run clean && tb --watch"
},
"author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io/)",
"license": "MIT",
"dependencies": {
"@preact/signals": "^1.3.0",
"highlight.js": "^11.9.0",
"htm": "^3.1.1",
"mine.css": "^9.0.1",
"preact": "^10.24.0",
"preact-render-to-string": "^6.5.11",
"top-bun": "../../."
},
"devDependencies": {
"npm-run-all2": "^6.0.0"
}
}
3 changes: 3 additions & 0 deletions examples/preact/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Preact example

This is a preact example.
4 changes: 4 additions & 0 deletions examples/preact/src/globals/global.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-ignore
import { toggleTheme } from 'mine.css'
// @ts-ignore
window.toggleTheme = toggleTheme
3 changes: 3 additions & 0 deletions examples/preact/src/globals/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import 'mine.css/dist/mine.css';
@import 'mine.css/dist/layout.css';
@import 'highlight.js/styles/github-dark-dimmed.css';
55 changes: 55 additions & 0 deletions examples/preact/src/isomorphic/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { html, Component } from 'htm/preact'
import { render } from 'preact'
import { useCallback } from 'preact/hooks'
import { useSignal, useComputed } from '@preact/signals'

const Header = ({ name }) => html`<h1>${name} List</h1>`

const Footer = props => {
const count = useSignal(0)
const double = useComputed(() => count.value * 2)

const handleClick = useCallback(() => {
count.value++
}, [count])

return html`<footer ...${props}>
${count}
${double}
${props.children}
<button onClick=${handleClick}>Click</button>
</footer>`
}

class App extends Component {
addTodo () {
const { todos = [] } = this.state
this.setState({ todos: todos.concat(`Item ${todos.length}`) })
}

render ({ page }, { todos = [] }) {
return html`
<div class="app">
<${Header} name="ToDo's (${page})" />
<ul>
${todos.map(todo => html`
<li key=${todo}>${todo}</li>
`)}
</ul>
<button onClick=${() => this.addTodo()}>Add Todo</button>
<${Footer}>footer content here<//>
</div>
`
}
}

export const page = () => html`
<${App}/>
<${Footer}>footer content here<//>
<${Footer}>footer content here<//>
`

if (typeof window !== 'undefined') {
const renderTarget = document.querySelector('.app-main')
render(page(), renderTarget)
}
5 changes: 5 additions & 0 deletions examples/preact/src/isomorphic/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { page } from './client.js'

export default () => {
return page()
}
58 changes: 58 additions & 0 deletions examples/preact/src/layouts/root.layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// @ts-ignore
import { html } from 'htm/preact'
import { render } from 'preact-render-to-string'

/**
* @template T extends object
* @typedef {import('../build-pages/resolve-layout.js').LayoutFunction<T>} LayoutFunction
*/

/**
* Build all of the bundles using esbuild.
*
* @type {LayoutFunction<{
* title: string,
* siteName: string,
* defaultStyle: boolean,
* basePath: string
* }>}
*/
export default function defaultRootLayout ({
vars: {
title,
siteName = 'TopBun',
basePath,
/* defaultStyle = true Set this to false in global or page to disable the default style in the default layout */
},
scripts,
styles,
children,
/* pages */
/* page */
}) {
return /* html */`
<!DOCTYPE html>
<html>
${render(html`
<head>
<meta charset="utf-8" />
<title>${title ? `${title}` : ''}${title && siteName ? ' | ' : ''}${siteName}</title>
<meta name="viewport" content="width=device-width, user-scalable=no" />
${scripts
? scripts.map(script => html`<script type='module' src="${script.startsWith('/') ? `${basePath ?? ''}${script}` : script}" />`)
: null}
${styles
? styles.map(style => html`<link rel="stylesheet" href="${style.startsWith('/') ? `${basePath ?? ''}${style}` : style}" />`)
: null}
</head>
`)}
${render(html`
<body class="safe-area-inset">
<main class="mine-layout app-main">
${typeof children === 'string' ? html([children]) : children /* Support both uhtml and string children. Optional. */}
</main>
</body>
`)}
</html>
`
}
9 changes: 3 additions & 6 deletions lib/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,10 @@ import { ensureDest } from './helpers/ensure-dest.js'
* }
*/
export async function builder (src, dest, opts) {
/** @type {BuildStepErrors} */
const errors = []
/** @type {BuildStepWarnings} */
const warnings = []
const errors = [] /** @type {BuildStepErrors} */
const warnings = [] /** @type {BuildStepWarnings} */

/** @type {SiteData} */
const siteData = await identifyPages(src, opts)
const siteData = await identifyPages(src, opts) /** @type {SiteData} */

errors.push(...siteData.errors)
warnings.push(...siteData.warnings)
Expand Down
6 changes: 4 additions & 2 deletions lib/helpers/top-bun-warning.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/** @typedef { 'TOP_BUN_WARNING_DUPLICATE_LAYOUT' |
/**
* @typedef { 'TOP_BUN_WARNING_DUPLICATE_LAYOUT' |
* 'TOP_BUN_WARNING_DUPLICATE_LAYOUT_STYLE' |
* 'TOP_BUN_WARNING_ORPHANED_LAYOUT_STYLE' |
* 'TOP_BUN_WARNING_DUPLICATE_LAYOUT_CLIENT' |
Expand All @@ -8,7 +9,8 @@
* 'TOP_BUN_WARNING_DUPLICATE_GLOBAL_STYLE' |
* 'TOP_BUN_WARNING_DUPLICATE_GLOBAL_CLIENT' |
* 'TOP_BUN_WARNING_DUPLICATE_GLOBAL_VARS'
* } TopBunWarningCode */
* } TopBunWarningCode
*/

/**
* @typedef TopBunWarning
Expand Down

0 comments on commit 72ce635

Please sign in to comment.