Package Exports
- lambda.html
- lambda.html/dist/src/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (lambda.html) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Lambda.html
A type-safe, zero-dependency HTML builder for TypeScript with built-in XSS protection and first-class HTMX support.
const page = Div([
H1("Welcome").setClass("text-3xl font-bold"),
Button("Load More")
.setHtmx(hx("/api/items", {
trigger: "click", // β IDE suggests: "click" | "load" | "revealed" | ...
swap: "beforeend", // β IDE suggests: "innerHTML" | "outerHTML" | ...
target: closest("ul"), // β Type-safe selector helper
}))
]).setClass("container mx-auto p-8");Why Lambda.html?
π― IDE-Powered Development
Lambda.html's type system provides intelligent autocomplete for everythingβHTML attributes, HTMX configurations, CSS classes, and more. Your IDE becomes your documentation.
// Your IDE suggests all valid trigger options as you type:
Button("Save").setHtmx(hx("/api/save", {
trigger: "cl" // IDE shows: click | change | load | revealed | intersect | ...
// β Autocomplete appears here!
}))
// Complex triggers with modifiers? Also fully typed:
Input().setHtmx(hx("/api/search", {
trigger: "keyup changed delay:300ms" // β Valid typed trigger
// β IDE validates modifier syntax
}))π Compile-Time Safety
Catch errors before they reach production:
// β
Compiles - valid swap strategy
Div().setHtmx(hx("/api", { swap: "innerHTML" }))
// β Type Error - "inner" is not a valid swap strategy
Div().setHtmx(hx("/api", { swap: "inner" }))
// ~~~~~~~
// Type '"inner"' is not assignable to type 'HxSwap'
// β
Compiles - valid input type
Input().setType("email").setPattern("[a-z]+@[a-z]+\\.[a-z]+")
// β Type Error - setPattern doesn't exist on Div
Div().setPattern("[a-z]+")
// ~~~~~~~~~~ Property 'setPattern' does not exist on type 'Tag'π‘οΈ Built-in XSS Protection
All content is automatically escapedβno configuration needed:
const userInput = '<script>alert("xss")</script>';
render(Div(userInput));
// Output: <div><script>alert("xss")</script></div>β‘ Zero Dependencies, Tiny Footprint
Pure TypeScript. No runtime overhead. Perfect for server-side rendering.
Installation
npm install lambda.htmlQuick Start
import { Div, H1, P, Button, render, hx } from 'lambda.html';
const page = Div([
H1("Welcome to Lambda.html")
.setClass("text-3xl font-bold"),
P("Build type-safe HTML with confidence.")
.setClass("text-gray-600 mt-2"),
Button("Get Started")
.setClass("bg-blue-500 text-white px-4 py-2 rounded mt-4")
.setHtmx(hx("/api/start", { method: "post" }))
]).setClass("container mx-auto p-8");
console.log(render(page));Output:
<div class="container mx-auto p-8">
<h1 class="text-3xl font-bold">Welcome to Lambda.html</h1>
<p class="text-gray-600 mt-2">Build type-safe HTML with confidence.</p>
<button class="bg-blue-500 text-white px-4 py-2 rounded mt-4"
hx-post="/api/start">Get Started</button>
</div>Table of Contents
- IDE Autocomplete in Action
- Type-Safe HTMX
- XSS Protection
- HTML Elements
- Control Flow
- Composable Components
- API Reference
IDE Autocomplete in Action
Lambda.html transforms your IDE into a powerful documentation tool. Here's what you get:
HTMX Triggers
// As you type, your IDE suggests all valid triggers:
.setHtmx(hx("/api", {
trigger: "|" // Cursor here shows:
}))
// Suggestions:
// click - Standard click event
// change - Input change event
// submit - Form submission
// load - Page load
// revealed - Element scrolled into view
// intersect - Intersection observer
// keyup - Key release
// mouseenter - Mouse enters element
// every 1s - Polling every second
// sse:event - Server-sent event
// ...and 20+ more!HTMX Swap Strategies
.setHtmx(hx("/api", {
swap: "|" // Cursor here shows:
}))
// Suggestions:
// innerHTML - Replace inner content (default)
// outerHTML - Replace entire element
// beforebegin - Insert before element
// afterbegin - Insert at start of children
// beforeend - Insert at end of children
// afterend - Insert after element
// delete - Remove element
// none - No swap
//
// With modifiers:
// innerHTML scroll:top
// outerHTML transition:true
// beforeend showπͺtopHTMX Sync Strategies
.setHtmx(hx("/api", {
sync: "|" // Cursor here shows:
}))
// Suggestions:
// drop - Drop new request if one in flight
// abort - Abort current request
// replace - Same as abort
// queue - Queue requests
// queue first - Queue, process first only
// queue last - Queue, process last only
// queue all - Queue all requestsInput Types & Attributes
Input()
.setType("|") // IDE suggests: text | email | password | number | tel | url | ...
.setAutocomplete("|") // IDE suggests: on | off | email | username | current-password | ...Element-Specific Methods
// Only Th and Td have colspan/rowspan:
Th("Header").setColspan(2).setScope("col")
// ~~~~~~~~~~~ β Available on ThTag
// ~~~~~~~~~ β Available on ThTag
Div("Content").setColspan(2)
// ~~~~~~~~~~ β Error: Property 'setColspan' does not exist
// Only Form has action/method:
Form().setAction("/submit").setMethod("post")
// ~~~~~~~~~ β Available ~~~~~~~~~ β Available
// Only Input has min/max/step:
Input().setType("number").setMin(0).setMax(100).setStep(5)
// ~~~~~~ β ~~~~~~ β ~~~~~~~ βType-Safe HTMX
Lambda.html provides complete HTMX 2.0 support with full type safety.
Basic Requests
import { hx } from 'lambda.html';
// GET request (default)
Button("Load").setHtmx(hx("/api/items"))
// POST request
Button("Submit").setHtmx(hx("/api/submit", { method: "post" }))
// PUT request
Button("Update").setHtmx(hx("/api/update/123", { method: "put" }))
// PATCH request (new in HTMX 2.0)
Button("Patch").setHtmx(hx("/api/resource", { method: "patch" }))
// DELETE request
Button("Delete").setHtmx(hx("/api/delete/123", { method: "delete" }))Type-Safe Target Selectors
import { id, clss, closest, find, next, previous } from 'lambda.html';
// ID selector β "#content"
Button("Load").setHtmx(hx("/api", { target: id("content") }))
// Class selector β ".items"
Button("Update").setHtmx(hx("/api", { target: clss("items") }))
// Closest ancestor β "closest tr"
Button("Delete Row").setHtmx(hx("/api/delete", {
method: "delete",
target: closest("tr")
}))
// Find descendant β "find .content"
Div().setHtmx(hx("/api", { target: find(".content") }))
// Next sibling β "next div"
Button("Next").setHtmx(hx("/api", { target: next("div") }))
// Previous sibling β "previous li"
Button("Prev").setHtmx(hx("/api", { target: previous("li") }))Triggers with Modifiers
// Debounced search input
Input()
.setType("search")
.setName("q")
.setHtmx(hx("/api/search", {
trigger: "keyup changed delay:300ms", // β Fully typed!
target: "#search-results"
}))
// Throttled scroll
Div().setHtmx(hx("/api/more", {
trigger: "scroll throttle:500ms",
swap: "beforeend"
}))
// Load on reveal (lazy loading)
Div().setHtmx(hx("/api/content", { trigger: "revealed" }))
// Polling every 30 seconds
Div().setHtmx(hx("/api/notifications", { trigger: "every 30s" }))
// Multiple triggers
Button("Action").setHtmx(hx("/api/action", {
trigger: "click, keyup[key=='Enter']"
}))Swap Strategies with Modifiers
// Basic swaps
Div().setHtmx(hx("/api", { swap: "innerHTML" })) // Replace inner content
Div().setHtmx(hx("/api", { swap: "outerHTML" })) // Replace entire element
Div().setHtmx(hx("/api", { swap: "beforeend" })) // Append to children
// With scroll modifier
Div().setHtmx(hx("/api", { swap: "innerHTML scroll:top" }))
// With show modifier (scroll into view)
Div().setHtmx(hx("/api", { swap: "innerHTML showπͺtop" }))
// With transition
Div().setHtmx(hx("/api", { swap: "outerHTML transition:true" }))
// With timing
Div().setHtmx(hx("/api", { swap: "innerHTML swap:500ms settle:100ms" }))HTMX 2.0 Features
// Prompt dialog before request
Button("Rename").setHtmx(hx("/api/rename", {
method: "post",
prompt: "Enter new name:"
}))
// Disable elements during request
Button("Submit").setHtmx(hx("/api/submit", {
method: "post",
disabledElt: "this" // or "#submit-btn" or "closest form"
}))
// Out-of-band swaps
Div().setHtmx(hx("/api/data", { swapOob: true }))
Div().setHtmx(hx("/api/data", { swapOob: "true:#sidebar" }))
// Control attribute inheritance
Div().setHtmx(hx("/api", { disinherit: "*" })) // Disable all
Div().setHtmx(hx("/api", { inherit: "hx-target hx-swap" })) // Force specific
// Prevent history snapshot
Div().setHtmx(hx("/api/modal", { history: false }))
// Preserve element during swap (e.g., video player)
Video().setId("player").setHtmx(hx("/api/page", { preserve: true }))
// Request configuration
Div().setHtmx(hx("/api/slow", { request: "timeout:5000" }))
// Boost links/forms to use AJAX
A("Page").setHref("/page").setHtmx(hx("/page", { boost: true }))
// Sync strategies
Button("Save").setHtmx(hx("/api/save", {
method: "post",
sync: "abort" // Abort previous request
}))
Input().setHtmx(hx("/api/search", {
sync: "queue last" // Queue, process last
}))Complete Form Example
Form([
Fieldset([
Legend("User Registration"),
Label("Email").setFor("email"),
Input()
.setType("email")
.setId("email")
.setName("email")
.setPlaceholder("you@example.com")
.setAutocomplete("email")
.setToggles(["required"]),
Label("Password").setFor("password"),
Input()
.setType("password")
.setId("password")
.setName("password")
.setMinlength(8)
.setAutocomplete("new-password")
.setToggles(["required"]),
Button("Register")
.setType("submit")
.setClass("bg-blue-500 text-white px-4 py-2 rounded")
]).setClass("space-y-4")
])
.setHtmx(hx("/api/register", {
method: "post",
swap: "outerHTML",
indicator: "#loading",
disabledElt: "find button"
}))XSS Protection
Lambda.html automatically escapes all text content and attributes. No configuration needed.
Automatic Text Escaping
// User input is automatically escaped
const userInput = '<script>alert("xss")</script>';
const element = Div(userInput);
console.log(render(element));
// Output: <div><script>alert("xss")</script></div>Automatic Attribute Escaping
// Malicious class names are escaped
const malicious = '"><script>alert(1)</script>';
const element = Div().setClass(malicious);
console.log(render(element));
// Output: <div class=""><script>alert(1)</script>"></div>Raw Content for Scripts & Styles
Script and Style elements are intentionally not escaped (they contain code, not user content):
// Script content preserved for valid JavaScript
Script(`
if (count < 10 && count > 0) {
console.log('valid');
}
`)
// Output: <script>if (count < 10 && count > 0) { console.log('valid'); }</script>
// Style content preserved for valid CSS
Style(`
.card > .title { content: "a & b"; }
`)
// Output: <style>.card > .title { content: "a & b"; }</style>Safe Dynamic Content
// Building HTML from user data is always safe
function UserCard(user: { name: string; bio: string }): View {
return Div([
H2(user.name), // β Escaped automatically
P(user.bio), // β Escaped automatically
]).setClass("user-card");
}
// Even malicious data is safely rendered
const user = {
name: '<script>steal(cookies)</script>',
bio: '"><img src=x onerror=alert(1)>'
};
render(UserCard(user));
// All content properly escaped - XSS prevented!HTML Elements
Lambda.html provides 60+ HTML elements with typed attribute methods.
Element Chaining
All elements support fluent method chaining:
const card = Div("Content")
.setId("my-card")
.setClass("card shadow-lg")
.addClass("hover:shadow-xl")
.setStyle("max-width: 400px")
.addAttribute("data-testid", "card-component")
.setHtmx(hx("/api/card", { trigger: "click" }));Nested Elements
// Single child
Div(P("Paragraph inside div"))
// Multiple children as array
Div([
H1("Title"),
P("First paragraph"),
P("Second paragraph")
])
// Mixed content
Div([
"Text node",
Strong("Bold text"),
" more text"
])Form Elements
// Text input with validation
Input()
.setType("email")
.setName("email")
.setPlaceholder("Enter your email")
.setPattern("[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$")
.setAutocomplete("email")
.setToggles(["required"])
// Number input with constraints
Input()
.setType("number")
.setName("quantity")
.setMin(1)
.setMax(100)
.setStep(5)
// Textarea
Textarea()
.setName("message")
.setPlaceholder("Enter your message")
.setRows(5)
.setMaxlength(500)
// Select with optgroups
Select([
Option("Select a country...").setValue(""),
Optgroup([
Option("United States").setValue("us"),
Option("Canada").setValue("ca"),
]).setLabel("North America"),
Optgroup([
Option("United Kingdom").setValue("uk"),
Option("Germany").setValue("de"),
]).setLabel("Europe"),
]).setName("country").setToggles(["required"])Table Elements
Table([
Caption("Monthly Sales Report"),
Thead(
Tr([
Th("Product").setScope("col"),
Th("Q1").setScope("col"),
Th("Q2").setScope("col"),
Th("Total").setScope("col").setColspan(2),
])
),
Tbody([
Tr([
Th("Widget A").setScope("row"),
Td("$1,000"),
Td("$1,500"),
Td("$2,500").setColspan(2),
]),
]),
Tfoot(
Tr([
Th("Total").setScope("row"),
Td("$3,000").setColspan(3),
])
),
]).setClass("w-full border-collapse")Media Elements
// Responsive image with lazy loading
Img()
.setSrc("hero.jpg")
.setAlt("Hero image")
.setSrcset("hero-400.jpg 400w, hero-800.jpg 800w")
.setSizes("(max-width: 600px) 400px, 800px")
.setLoading("lazy")
.setDecoding("async")
// Video with multiple sources
Video([
Source().setSrc("video.webm").setType("video/webm"),
Source().setSrc("video.mp4").setType("video/mp4"),
Track()
.setSrc("captions.vtt")
.setKind("subtitles")
.setSrclang("en")
.setLabel("English")
.setDefault(),
"Your browser does not support video."
])
.setControls()
.setPoster("poster.jpg")
.setPreload("metadata")
// Picture element for art direction
Picture([
Source()
.setSrcset("hero-mobile.jpg")
.setMedia("(max-width: 600px)"),
Source()
.setSrcset("hero-desktop.jpg")
.setMedia("(min-width: 601px)"),
Img().setSrc("hero-fallback.jpg").setAlt("Hero"),
])Interactive Elements
// Details/Summary (accordion)
Details([
Summary("Click to expand"),
P("Hidden content revealed when opened."),
]).setOpen()
// Dialog (modal)
Dialog([
H2("Confirm Action"),
P("Are you sure you want to proceed?"),
Button("Cancel").addAttribute("onclick", "this.closest('dialog').close()"),
Button("Confirm").setClass("bg-blue-500 text-white"),
]).setId("confirm-modal")
// Progress and Meter
Progress().setValue(70).setMax(100)
Meter().setValue(0.7).setMin(0).setMax(1).setLow(0.3).setHigh(0.8).setOptimum(0.5)Control Flow
Lambda.html provides functional control flow for conditional and iterative rendering.
IfThen / IfThenElse
import { IfThen, IfThenElse } from 'lambda.html';
// Conditional rendering
function UserBadge(user: { isAdmin: boolean; isPremium: boolean }): View {
return Div([
IfThen(user.isAdmin, () =>
Span("Admin").setClass("badge badge-red")
),
IfThen(user.isPremium, () =>
Span("Premium").setClass("badge badge-gold")
),
]);
}
// If-else rendering
function LoginStatus(user: User | null): View {
return IfThenElse(
user !== null,
() => Span(`Welcome, ${user!.name}`),
() => A("Login").setHref("/login")
);
}SwitchCase
import { SwitchCase } from 'lambda.html';
type Status = 'pending' | 'approved' | 'rejected';
function StatusBadge(status: Status): View {
return SwitchCase([
{ condition: status === 'pending', component: () => Span("β³ Pending").setClass("text-yellow-600") },
{ condition: status === 'approved', component: () => Span("β
Approved").setClass("text-green-600") },
{ condition: status === 'rejected', component: () => Span("β Rejected").setClass("text-red-600") },
], () => Span("Unknown").setClass("text-gray-600"));
}ForEach Variants
import { ForEach, ForEach1, ForEach2, ForEach3, Repeat } from 'lambda.html';
const items = ["Apple", "Banana", "Cherry"];
// Basic iteration
Ul(ForEach(items, item => Li(item)))
// With index
Ol(ForEach1(items, (item, index) =>
Li(`${index + 1}. ${item}`)
))
// Range iteration (0 to n-1)
Div(ForEach2(5, i =>
Span(`Item ${i}`).setClass("inline-block p-2")
))
// Range iteration (start to end-1)
Div(ForEach3(1, 6, i =>
Button(`Page ${i}`).setClass("px-3 py-1")
))
// Repeat n times
Div(Repeat(5, () => Span("β")))Composable Components
Build reusable, type-safe components as pure functions.
Button Component
interface ButtonProps {
text: string;
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
htmx?: HTMX;
}
function StyledButton(props: ButtonProps): View {
const variants = {
primary: 'bg-blue-500 hover:bg-blue-600 text-white',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800',
danger: 'bg-red-500 hover:bg-red-600 text-white',
};
const sizes = {
sm: 'px-2 py-1 text-sm',
md: 'px-4 py-2',
lg: 'px-6 py-3 text-lg',
};
const button = Button(props.text)
.setClass(`rounded font-medium transition-colors
${variants[props.variant ?? 'primary']}
${sizes[props.size ?? 'md']}
${props.disabled ? 'opacity-50 cursor-not-allowed' : ''}
`.replace(/\s+/g, ' ').trim());
if (props.disabled) button.setDisabled();
if (props.htmx) button.setHtmx(props.htmx);
return button;
}
// Usage
StyledButton({ text: "Save", variant: "primary", htmx: hx("/api/save", { method: "post" }) })
StyledButton({ text: "Cancel", variant: "secondary" })
StyledButton({ text: "Delete", variant: "danger", disabled: true })Card Component
interface CardProps {
title: string;
content: View;
footer?: View;
image?: string;
}
function Card(props: CardProps): View {
return Div([
IfThen(!!props.image, () =>
Img()
.setSrc(props.image!)
.setAlt(props.title)
.setClass("w-full h-48 object-cover")
.setLoading("lazy")
),
Div([
H3(props.title).setClass("text-xl font-semibold mb-2"),
Div(props.content).setClass("text-gray-600"),
]).setClass("p-4"),
IfThen(!!props.footer, () =>
Div(props.footer!).setClass("px-4 py-3 bg-gray-50 border-t")
),
]).setClass("bg-white rounded-lg shadow-md overflow-hidden");
}Data Table Component
interface Column<T> {
key: keyof T;
header: string;
render?: (value: T[keyof T], row: T) => View;
}
function DataTable<T extends Record<string, any>>(
columns: Column<T>[],
data: T[],
options?: { striped?: boolean; hoverable?: boolean }
): View {
return Table([
Thead(
Tr(ForEach(columns, col =>
Th(col.header).setScope("col").setClass("px-4 py-3 text-left font-semibold")
)).setClass("bg-gray-100")
),
Tbody(
ForEach1(data, (row, index) =>
Tr(ForEach(columns, col => {
const value = row[col.key];
const content = col.render ? col.render(value, row) : String(value);
return Td(content).setClass("px-4 py-3");
}))
.addClass(options?.hoverable ? 'hover:bg-gray-50' : '')
.addClass(options?.striped && index % 2 ? 'bg-gray-50' : '')
)
),
]).setClass("w-full border-collapse");
}
// Usage
interface User { id: number; name: string; email: string; role: string; }
DataTable<User>(
[
{ key: "name", header: "Name" },
{ key: "email", header: "Email" },
{
key: "role",
header: "Role",
render: (value) => Span(String(value))
.setClass(value === "Admin" ? "text-red-600 font-bold" : "text-gray-600")
},
],
users,
{ striped: true, hoverable: true }
)Infinite Scroll Component
function InfiniteScrollList(items: Item[], page: number): View {
return Div([
Ul(
ForEach(items, item =>
Li([
H3(item.title).setClass("font-medium"),
P(item.description).setClass("text-gray-600 text-sm"),
]).setClass("p-4 border-b")
)
).setId("item-list"),
// Load more trigger - fires when scrolled into view
Div("Loading...")
.setId("load-more")
.setClass("p-4 text-center text-gray-500")
.setHtmx(hx(`/api/items?page=${page + 1}`, {
trigger: "revealed",
swap: "outerHTML",
}))
]);
}API Reference
Element Functions
| Category | Elements |
|---|---|
| Structure | Div, Main, Header, Footer, Section, Article, Nav, Aside, Figure, Figcaption, Address, Hgroup, Search |
| Headings | H1, H2, H3, H4, H5, H6 |
| Text | P, Span, Strong, Em, B, I, U, S, Mark, Small, Sub, Sup, Blockquote, Pre, Code, Abbr, Cite, Q, Dfn, Kbd, Samp, Var |
| Breaks | Br, Hr, Wbr |
| Lists | Ul, Ol, Li, Dl, Dt, Dd, Menu |
| Tables | Table, Thead, Tbody, Tfoot, Tr, Th, Td, Caption, Colgroup, Col |
| Forms | Form, Input, Textarea, Button, Label, Select, Option, Optgroup, Datalist, Fieldset, Legend, Output |
| Interactive | Details, Summary, Dialog |
| Media | Img, Picture, Source, Video, Audio, Track, Canvas |
| SVG | Svg, Path, Circle, Rect, Line, Polygon, Polyline, Ellipse, G, Defs, Use, Text, Tspan |
| Embedded | Iframe, ObjectEl, Embed, MapEl, Area |
| Links | A |
| Document | HTML, Head, Body, Title, Meta, Link, Style, Script, Base, Noscript, Template |
| Data | Time, Data, Progress, Meter, Slot |
| Utility | El (custom), Empty, Overlay |
Common Methods (All Tags)
| Method | Description |
|---|---|
.setId(id) |
Set element ID |
.setClass(classes) |
Set CSS classes |
.addClass(class) |
Append CSS class |
.setStyle(css) |
Set inline styles |
.addAttribute(key, value) |
Add custom attribute |
.setHtmx(hx(...)) |
Add HTMX behavior |
.setToggles([...]) |
Add boolean attributes (required, disabled, etc.) |
Control Flow
| Function | Description |
|---|---|
IfThen(condition, thenFn) |
Render if condition is true |
IfThenElse(condition, thenFn, elseFn) |
Conditional rendering |
SwitchCase(cases, defaultFn) |
Multi-branch conditional |
ForEach(items, renderFn) |
Iterate over items |
ForEach1(items, renderFn) |
Iterate with index |
ForEach2(n, renderFn) |
Range 0 to n-1 |
ForEach3(start, end, renderFn) |
Range start to end-1 |
Repeat(n, renderFn) |
Repeat n times |
HTMX Helper
hx(endpoint: string, options?: {
// HTTP Method
method?: 'get' | 'post' | 'put' | 'patch' | 'delete';
// Targeting
target?: string; // CSS selector or extended selector
swap?: HxSwap; // Swap strategy
swapOob?: boolean | string; // Out-of-band swap
select?: string; // Select from response
selectOob?: string; // Select OOB content
// Triggering
trigger?: HxTrigger; // Event trigger
// URL
pushUrl?: boolean | string; // Push to history
replaceUrl?: boolean | string; // Replace in history
// Data
vals?: object | string; // Additional values
headers?: object; // Custom headers
include?: string; // Include elements
params?: string; // Filter params
encoding?: 'multipart/form-data';
// Validation
validate?: boolean;
confirm?: string; // Confirmation dialog
prompt?: string; // Prompt dialog
// Loading
indicator?: string; // Loading indicator
disabledElt?: string; // Disable during request
// Sync
sync?: HxSync; // Request synchronization
// Other
ext?: string; // Extensions
disinherit?: string; // Disable inheritance
inherit?: string; // Force inheritance
history?: boolean; // History snapshot
historyElt?: boolean;
preserve?: boolean; // Preserve element
request?: string; // Request config
boost?: boolean; // Boost links/forms
disable?: boolean; // Disable htmx
})Selector Helpers
import { id, clss, closest, find, next, previous } from 'lambda.html';
id("content") // β "#content"
clss("items") // β ".items"
closest("tr") // β "closest tr"
find(".content") // β "find .content"
next("div") // β "next div"
next() // β "next"
previous("li") // β "previous li"
previous() // β "previous"License
ISC Β© Toni K. Turk