Browser APIs
@praxisjs/composables browser composable classes — MediaQuery, ColorScheme, Mouse, KeyCombo, Idle, Clipboard, Geolocation, TimeAgo, and Pagination.
Browser APIs
Browser API composables from @praxisjs/composables. Bind them to any component with @Compose to get reactive browser state as class properties.
npm install @praxisjs/composablespnpm add @praxisjs/composablesyarn add @praxisjs/composablesbun add @praxisjs/composablesMediaQuery
Reactive CSS media query matching. Updates whenever the query result changes.
@Compose(MediaQuery, '(max-width: 768px)')
mobile!: MediaQuery
render() {
return () => this.mobile.matches ? <MobileView /> : <DesktopView />
}Constructor: new MediaQuery(query: string)
Properties: matches: boolean
ColorScheme
Detects the user's preferred color scheme via prefers-color-scheme. Updates if the user changes their system preference.
@Compose(ColorScheme)
scheme!: ColorScheme
render() {
return <div class={() => this.scheme.isDark ? 'dark' : 'light'}>...</div>
}Properties: isDark: boolean, isLight: boolean
Mouse
Tracks the cursor position in the viewport.
@Compose(Mouse)
mouse!: Mouse
render() {
return (
<div
style={() => ({
transform: `translate(${this.mouse.x}px, ${this.mouse.y}px)`
})}
/>
)
}Properties: x: number, y: number
KeyCombo
Detects keyboard shortcut combinations. The pressed signal becomes true while the combo is held.
@Compose(KeyCombo, 'ctrl+s')
saveShortcut!: KeyCombo
onMount() {
effect(() => {
if (this.saveShortcut.pressed) this.save()
})
}Constructor: new KeyCombo(combo: string) — accepts ctrl, shift, alt, meta modifiers with + as separator.
Properties: pressed: boolean
Idle
Detects user inactivity by monitoring mouse, keyboard, and touch events. Default timeout is 60 seconds.
@Compose(Idle, 30_000) // idle after 30s of inactivity
activity!: Idle
render() {
return () => this.activity.idle ? <ScreenSaver /> : <AppContent />
}Constructor: new Idle(timeout?: number) — timeout in ms.
Properties: idle: boolean
Clipboard
Read/write clipboard access. copied resets to false after resetDelay ms (default: 2000).
@Compose(Clipboard)
clipboard!: Clipboard
render() {
return (
<button onClick={() => this.clipboard.copy('Hello!')}>
{() => this.clipboard.copied ? '✓ Copied!' : 'Copy'}
</button>
)
}Properties: copied: boolean, content: string, copy(text): Promise<void>
Geolocation
One-shot geolocation lookup via the Geolocation API.
@Compose(Geolocation, { enableHighAccuracy: true })
geo!: Geolocation
render() {
return (
<div>
{() => this.geo.loading && <p>Locating...</p>}
{() => this.geo.error && <p>Location access denied.</p>}
{() => !this.geo.loading && !this.geo.error && (
<p>Lat: {this.geo.lat?.toFixed(4)}, Lon: {this.geo.lng?.toFixed(4)}</p>
)}
</div>
)
}Constructor: new Geolocation(options?: PositionOptions)
Properties: lat: number | null, lng: number | null, error: GeolocationPositionError | null, loading: boolean
TimeAgo
Relative time formatting ("3 minutes ago", "2 days ago"), updated automatically while the component is mounted. Instead of polling, it sets one timer for the exact moment the text changes: every second for "30 seconds ago", once an hour or less for "3 days ago". The timer is re-armed when the source changes.
import { getter } from '@praxisjs/decorators'
@State() postedAt = new Date('2026-01-01')
// getter() wraps the property as () => this.postedAt — TimeAgo needs a callable source
@Compose(TimeAgo, getter('postedAt'))
timeAgo!: TimeAgo
render() {
return <p>Posted {() => this.timeAgo.value}</p>
// → "4 months ago"
}Constructor: new TimeAgo(source: Signal<Date> | (() => Date), locale?: string)
Properties: value: string
Pagination
Manages pagination state — current page, total pages, and navigation methods.
@Compose(Pagination, { total: 100, pageSize: 10 })
pages!: Pagination
render() {
return (
<div>
<p>Page {() => this.pages.page} of {() => this.pages.totalPages}</p>
<button disabled={() => !this.pages.hasPrev} onClick={() => this.pages.prev()}>← Prev</button>
<button disabled={() => !this.pages.hasNext} onClick={() => this.pages.next()}>Next →</button>
</div>
)
}Constructor: new Pagination({ total, pageSize, initial? })
| Property/Method | Description |
|---|---|
page | Current page (1-based) |
totalPages | Total number of pages |
offset | Items to skip (useful for API offset or array slice) |
hasPrev / hasNext | Navigation availability |
prev() / next() | Navigate one page |
goTo(n) | Jump to a specific page |
first() / last() | Jump to first or last page |