Skip to content

API Reference

Documentação completa de todas as funções, componentes e tipos exportados pelo Slash.

Terminal window
bun add @ezbug/slash
# ou
npm install @ezbug/slash

Cria elementos DOM usando hyperscript.

function h(
tag: string | Function,
props?: Props | null,
...children: Child[]
): VNode

Parâmetros:

  • tag: Nome da tag HTML ou componente funcional
  • props: Propriedades do elemento (opcional)
  • children: Filhos do elemento (podem ser strings, números, VNodes, arrays)

Retorna: VNode - Representação virtual do elemento

Exemplo:

import { h } from '@ezbug/slash'
const element = h('div', { class: 'container' },
h('h1', null, 'Hello'),
h('p', null, 'World')
)

Template tag que converte template strings em VNodes usando HTM.

const html: HTMTemplate

Uso:

import { html } from '@ezbug/slash'
const element = html`
<div class="container">
<h1>Hello</h1>
<p>World</p>
</div>
`

Interpolação:

const name = 'John'
const items = ['a', 'b', 'c']
const element = html`
<div>
<h1>Hello ${name}</h1>
<ul>
${items.map(item => html`<li>${item}</li>`)}
</ul>
</div>
`

Monta um VNode no DOM.

function render(
vnode: VNode,
container: HTMLElement
): void

Parâmetros:

  • vnode: VNode para renderizar
  • container: Elemento DOM onde montar

Exemplo:

import { html, render } from '@ezbug/slash'
const App = html`<h1>My App</h1>`
const root = document.getElementById('app')
if (root) {
render(App, root)
}

Remove um nó do DOM e limpa recursos.

function destroyNode(element: HTMLElement): void

Parâmetros:

  • element: Elemento DOM para destruir

Uso:

import { destroyNode } from '@ezbug/slash'
const element = document.getElementById('my-component')
if (element) {
destroyNode(element)
}

Cria um estado reativo com observadores.

function createState<T>(
initialValue: T,
options?: StateOptions
): State<T>

Parâmetros:

  • initialValue: Valor inicial do estado
  • options: Opções de configuração (opcional)

Opções:

interface StateOptions {
history?: boolean // Habilita histórico (time-travel debug)
maxHistory?: number // Número máximo de histórico (padrão: 50)
}

Retorna: Objeto State<T> com métodos:

Retorna o valor atual do estado.

get(): T

Exemplo:

const count = createState(0)
console.log(count.get()) // 0

Atualiza o valor do estado e notifica observadores.

set(newValue: T): void

Exemplo:

const count = createState(0)
count.set(5)
console.log(count.get()) // 5

Registra um observador que é chamado quando o estado muda.

watch(callback: (newValue: T, oldValue: T) => void): () => void

Parâmetros:

  • callback: Função chamada ao mudar estado

Retorna: Função de cleanup para remover o observador

Exemplo:

const count = createState(0)
const unwatch = count.watch((newVal, oldVal) => {
console.log(`Changed from ${oldVal} to ${newVal}`)
})
count.set(5) // Logs: "Changed from 0 to 5"
// Remover observador
unwatch()

Exemplo Completo:

import { createState, html } from '@ezbug/slash'
const count = createState(0, { history: true })
// Componente que usa estado
const Counter = () => {
const value = count.get()
return html`
<div>
<p>Count: ${value}</p>
<button onclick=${() => count.set(value + 1)}>
Increment
</button>
</div>
`
}

Agrupa múltiplas atualizações de estado em um único ciclo de renderização.

function batch(fn: () => void): void

Parâmetros:

  • fn: Função que contém as atualizações

Exemplo:

import { createState, batch } from '@ezbug/slash'
const name = createState('')
const age = createState(0)
// Sem batch: 2 renders
name.set('John')
age.set(30)
// Com batch: 1 render
batch(() => {
name.set('John')
age.set(30)
})

Renderiza um VNode para string HTML (síncrono).

function renderToString(vnode: VNode): string

Parâmetros:

  • vnode: VNode para renderizar

Retorna: String HTML

Exemplo:

import { html, renderToString } from '@ezbug/slash'
const App = html`<h1>Hello SSR</h1>`
const htmlString = renderToString(App)
console.log(htmlString) // "<h1>Hello SSR</h1>"

Renderiza um VNode para stream (para grandes páginas).

function renderToStream(vnode: VNode): ReadableStream

Parâmetros:

  • vnode: VNode para renderizar

Retorna: ReadableStream que pode ser pipeado

Exemplo (Node.js):

import { html, renderToStream } from '@ezbug/slash'
import { Writable } from 'stream'
const App = html`<h1>Hello Streaming</h1>`
const stream = renderToStream(App)
response.writeHead(200, { 'Content-Type': 'text/html' })
stream.pipe(response)

Template tag para criar strings HTML seguras com escapamento.

const htmlString: (strings: TemplateStringsArray, ...values: any[]) => string

Uso:

import { htmlString } from '@ezbug/slash'
const title = 'My Page'
const html = htmlString`
<!DOCTYPE html>
<html>
<head><title>${title}</title></head>
<body>
<div id="app"></div>
</body>
</html>
`

Cria um loader isomórfico para data fetching.

function createLoader<T, Args extends any[] = []>(
fetchFn: (...args: Args) => T | Promise<T>,
options?: LoaderOptions
): LoaderFunction<T, Args>

Parâmetros:

  • fetchFn: Função que carrega os dados
  • options: Configurações do loader

Opções:

interface LoaderOptions {
ttl?: number // Tempo de vida do cache (ms)
key?: (...args: any[]) => string // Função para gerar chave de cache
onError?: (error: Error) => void // Callback de erro
staleWhileRevalidate?: boolean // Retorna cache stale enquanto revalida
}

Retorna: Função loader que pode ser chamada para carregar dados

Exemplo:

import { createLoader } from '@ezbug/slash'
interface User {
id: string
name: string
}
const userLoader = createLoader<User>(
async (id: string) => {
const res = await fetch(`/api/users/${id}`)
return res.json()
},
{
ttl: 5 * 60 * 1000, // 5 minutos
key: (id) => `user:${id}`
}
)
// Uso
const user = userLoader('123') // Carrega e cacheia
const sameUser = userLoader('123') // Retorna do cache

Invalida o cache de um loader.

function invalidateLoader<T, Args extends any[]>(
loader: LoaderFunction<T, Args>,
...args: Args
): void

Parâmetros:

  • loader: Loader para invalidar
  • args: Argumentos para gerar a chave (opcional)

Exemplo:

import { invalidateLoader } from '@ezbug/slash'
// Invalida cache específico
invalidateLoader(userLoader, '123')
// Invalida todo o cache do loader
invalidateLoader(userLoader)

Obtém o cache de loaders para hidratação no cliente.

function hydrateLoaderCache(): Record<string, any>

Retorna: Objeto com cache de todos os loaders

Exemplo (Servidor):

import { hydrateLoaderCache } from '@ezbug/slash'
const cache = hydrateLoaderCache()
const html = htmlString`
<!DOCTYPE html>
<html>
<head>
<script>
window.__LOADER_CACHE__ = ${JSON.stringify(cache)};
</script>
</head>
<body>...</body>
</html>
`

Detecta se o código está rodando no servidor.

function isServer(): boolean

Retorna: true se no servidor, false no cliente

Exemplo:

import { isServer } from '@ezbug/slash'
if (isServer()) {
// Código apenas para servidor
console.log('Running on server')
} else {
// Código apenas para cliente
console.log('Running on client')
}

Cria uma instância de router.

function createRouter(config: RouterConfig): Router

Configuração:

interface RouterConfig {
mode?: 'hash' | 'history' // Modo de navegação (padrão: 'hash')
routes: RouteConfig[] // Definição de rotas
scrollBehavior?: (to, from) => ScrollPosition
beforeEach?: (to, from) => boolean | { redirect: string }
afterEach?: (to, from) => void
}
interface RouteConfig {
path: string // Caminho da rota
component: () => VNode | Promise<VNode> // Componente (pode ser lazy)
beforeEnter?: (to, from) => boolean | { redirect: string }
meta?: Record<string, any> // Metadados customizados
}

Exemplo:

import { createRouter } from '@ezbug/slash'
const router = createRouter({
mode: 'history',
routes: [
{
path: '/',
component: () => import('./pages/Home')
},
{
path: '/users/:id',
component: () => import('./pages/UserDetail'),
meta: { requiresAuth: true }
}
],
beforeEach: (to, from) => {
console.log(`Navigating to ${to.path}`)
return true
}
})
router.init()

Componente que renderiza a rota atual.

function Router(props: { router: Router }): VNode

Uso:

import { html, Router } from '@ezbug/slash'
import { router } from './router'
const App = html`
<div>
<nav>...</nav>
${Router({ router })}
</div>
`

Componente para navegação client-side.

function Link(props: LinkProps): VNode
interface LinkProps {
to: string | { path: string; query?: Record<string, string> }
class?: string
activeClass?: string
children: Child | Child[]
}

Uso:

import { Link } from '@ezbug/slash'
const Nav = html`
<nav>
${Link({ to: '/', children: 'Home' })}
${Link({ to: '/about', children: 'About' })}
${Link({
to: { path: '/users', query: { page: '1' } },
children: 'Users'
})}
</nav>
`

Navega para uma rota programaticamente.

push(location: string | { path: string; query?: Record<string, string> }): void

Exemplo:

router.push('/about')
router.push({ path: '/users', query: { page: '2' } })

Substitui a rota atual (não adiciona ao histórico).

replace(location: string | { path: string; query?: Record<string, string> }): void

Volta uma página no histórico.

back(): void

Avança uma página no histórico.

forward(): void

Navega n páginas no histórico.

go(n: number): void

Exemplo:

router.go(-2) // Volta 2 páginas
router.go(1) // Avança 1 página

Retorna a rota atual.

getCurrentRoute(): RouteInfo | null
interface RouteInfo {
path: string
params: Record<string, string>
query: Record<string, string>
meta: Record<string, any>
}

Componente para capturar erros em componentes filhos.

function ErrorBoundary(props: ErrorBoundaryProps): VNode
interface ErrorBoundaryProps {
fallback?: (error: Error) => VNode
onError?: (error: Error) => void
children: VNode | VNode[]
}

Exemplo:

import { ErrorBoundary, html } from '@ezbug/slash'
const App = html`
${ErrorBoundary({
fallback: (error) => html`
<div class="error">
<h2>Something went wrong</h2>
<p>${error.message}</p>
</div>
`,
onError: (error) => {
console.error('Error caught:', error)
},
children: html`<MyComponent />`
})}
`

Wrapper para funções assíncronas que captura erros.

function catchAsync<T>(
fn: () => Promise<T>,
onError?: (error: Error) => void
): Promise<T | null>

Exemplo:

import { catchAsync } from '@ezbug/slash'
const data = await catchAsync(
async () => {
const res = await fetch('/api/data')
return res.json()
},
(error) => {
console.error('Fetch failed:', error)
}
)

Renderiza um VNode com tratamento de erro.

function safeRender(
vnode: VNode,
onError?: (error: Error) => VNode
): string

Uso (SSR):

import { safeRender } from '@ezbug/slash'
const html = safeRender(
App,
(error) => html`<h1>Error: ${error.message}</h1>`
)

Configura um handler global de erros.

function setupGlobalErrorHandler(
handler: (error: Error) => void
): void

Exemplo:

import { setupGlobalErrorHandler } from '@ezbug/slash'
setupGlobalErrorHandler((error) => {
console.error('Global error:', error)
// Enviar para serviço de logging
})

interface FormHelpers<T> {
values: State<T>
errors: State<Partial<Record<keyof T, string>>>
touched: State<Partial<Record<keyof T, boolean>>>
handleSubmit: (e: Event) => void
handleChange: (field: keyof T, value: any) => void
handleBlur: (field: keyof T) => void
reset: () => void
}

Exemplo de uso está na seção de Form Validation


Habilita/desabilita modo de desenvolvimento.

function setDevMode(enabled: boolean): void

Exemplo:

import { setDevMode } from '@ezbug/slash'
setDevMode(process.env.NODE_ENV === 'development')

Habilita/desabilita warnings no console.

function setWarningsEnabled(enabled: boolean): void

Verifica se está em modo dev.

function isDevMode(): boolean

Verifica se warnings estão habilitados.

function isWarningsEnabled(): boolean

Representação virtual de um nó DOM.

type VNode = ElementNode | TextNode | ComponentNode

Propriedades de um elemento.

interface Props {
[key: string]: any
class?: string
style?: string | Record<string, string>
onclick?: EventHandler
onchange?: EventHandler
// ... outros event handlers
}

Tipo retornado por createState().

interface State<T> {
get(): T
set(value: T): void
watch(callback: (newValue: T, oldValue: T) => void): () => void
}

Tipos válidos para children de elementos.

type Child =
| VNode
| string
| number
| boolean
| null
| undefined
| Child[]