AbsoluteJS

Vue Composables

@absolutejs/vue-composablesv0.3.3betaFrontend & UX

Small SSR-aware Vue composables — hydration gate, browser flag, debounced actions, and an async try/catch/notify wrapper — for Vue 3 apps.

@absolutejs/vue-composables is a small set of broadly-useful Vue composables for SSR-first apps: an SSR hydration gate, a browser-environment flag, a scope-safe debouncer, and an async-action wrapper that centralizes try/catch, loading flags, and toast notifications. Vue is a peer dependency, so it drops into any Vue 3 app — including AbsoluteJS Vue pages — without pulling in a second Vue copy.

#Installation

BASH
bun add @absolutejs/vue-composables

#Capabilities

Overview

A few small, broadly-useful Vue composables for AbsoluteJS (SSR-first) apps. Vue is a peer dependency.

Composables

useHydrated() — a ref that's false during SSR + the first client

render, then true after mount. Gate client-only data on it to avoid hydration mismatches: loading = !hydrated.value || actualLoading.value.

isBrowser — true on the client, false during SSR.

Show 10 more

useDebouncedAction(fn, delayMs?) — trailing-edge debouncer auto-cleared

on scope dispose; .trigger() (re)starts the delay.

useResizeObserver(target, callback, options?) — SSR-safe element

observer that coalesces notifications to the next animation frame and automatically cleans up when the target or Vue scope changes.

useAutoGrowTextarea(target, { maxHeight }) — keeps chat composers

content-sized until a reactive maximum, then switches to internal scrolling.

isTextSubmitKey(event) — recognizes plain Enter while excluding

Shift+Enter and IME composition confirmation.

runAsyncAction(task, options) — the try/catch/finally + notify +

console.error + loading-flag wrapper. Inject your toast once with configureAsyncNotifier({ success, error }).

Pagination

Apache-2.0

SSR hydration gate

useHydrated returns a ref that is false during SSR and the first client render, then true after mount — gate client-only data on it to avoid hydration mismatches.

Browser flag

isBrowser is true on the client and false during SSR, for quick environment checks outside component setup.

Debounced actions

useDebouncedAction gives a trailing-edge debouncer whose timer is auto-cleared on scope dispose; trigger() restarts the delay.

Async action wrapper

runAsyncAction wraps a task with try/catch/finally, a loading-flag callback, console.error, and success/error notifications.

Injectable notifier

configureAsyncNotifier injects your toast implementation once, so every runAsyncAction call site stays free of notification plumbing.

Outcomes

What you can build

Overview

A few small, broadly-useful Vue composables for AbsoluteJS (SSR-first) apps. Vue is a peer dependency.

Composables

useHydrated() — a ref that's false during SSR + the first client

Pagination

Apache-2.0

Hardening checklist

Production guidance

Make every external boundary explicitPin the deployed @absolutejs/vue-composables version, replace example or memory-backed dependencies with durable implementations, bound external calls, protect credentials, and emit enough evidence to retry or recover safely.

Follow in order

Troubleshooting path

1
Trace from the first failed boundary
Reproduce the smallest canonical @absolutejs/vue-composables example, confirm the supported entry point and version in the API explorer, then inspect the first boundary that did not produce its documented result.

#Async actions

Partial snippet

Working example for Async actions.

TS
import {
	configureAsyncNotifier,
	runAsyncAction,
	useHydrated
} from '@absolutejs/vue-composables';

configureAsyncNotifier({ success: toast.success, error: toast.error });

await runAsyncAction(() => api.save(payload), {
	successMessage: 'Saved',
	loading: (s) => (saving.value = s),
	onSuccess: () => emit('updated')
});

#Resize observation

Partial snippet

Working example for Resize observation.

TS
const panel = useTemplateRef<HTMLElement>('panel');

useResizeObserver(panel, ([entry]) => {
	if (entry) compact.value = entry.contentRect.width < 640;
});

#Quick Start

Partial snippet

Wire the notifier once, run async actions without repeated try/catch/loading boilerplate, and gate client-only state on hydration.

TS
import {
	configureAsyncNotifier,
	runAsyncAction,
	useHydrated
} from '@absolutejs/vue-composables';
import { computed } from 'vue';

// Inject your toast once, app-wide
configureAsyncNotifier({ error: toast.error, success: toast.success });

await runAsyncAction(() => api.save(payload), {
	loading: (s) => (saving.value = s),
	onSuccess: () => emit('updated'),
	successMessage: 'Saved'
});

// Gate client-only data to avoid hydration mismatches
const hydrated = useHydrated();
const loading = computed(() => !hydrated.value || actualLoading.value);

#Debounced Actions

Partial snippet

Debounce user input without managing timers — cleanup happens automatically on scope dispose.

TS
import { useDebouncedAction } from '@absolutejs/vue-composables';

// Trailing-edge debounce, auto-cleared when the component scope disposes
const search = useDebouncedAction(() => {
	void fetchResults(query.value);
}, 250);

// Each call (re)starts the delay
const onInput = () => search.trigger();
Lightweight by design
Vue 3.3+ is a peer dependency. The composables are deliberately small and framework-only — no AbsoluteJS runtime required, so they work in any Vue app.

Current package surface

What ships today

@absolutejs/vue-composablesv0.3.3 · betaFrontend & UXnpmSource