@arqel-dev/hooks — API Reference
10 hooks reusáveis. 11 entry points subpath tree-shakeable.
import { useResource, useArqelForm, useCanAccess, useFlash, useTable,
useAction, useFieldDependencies, useNavigation, useBreakpoint,
useArqelOptimistic } from '@arqel-dev/hooks';useResource<T>()
Lê page props + ResourceContext, retorna shape unificado.
const { resource, record, fields, form, table } = useResource<Post>();useArqelForm({ fields, record? })
Wrapper de Inertia useForm com defaults via buildInitialFormState.
const form = useArqelForm({ fields, record });
form.data.title // typed via FormValues
form.setData(name, v)
form.processing
form.errors
form.submit('post', route('arqel.resources.store'), { onSuccess: () => {} });Nota técnica: Inertia
useForm<T>sofre de "type instantiation excessively deep" comRecord<string, FormDataConvertible>—useArqelFormfaz cast bridgeuseForm as unknown as (data: FormValues) => InertiaFormProps<FormValues>para evitar TS2589 mantendo o tipo de retorno público.
useCanAccess(ability, record?)
const canEdit = useCanAccess('update', post);
const canExport = useCanAccess('exportData'); // global abilityRecord-level abilities têm precedência sobre globals (UX-only — ADR-017).
useFlash({ onMessage })
Callback once-per-new-message via useRef.
useFlash({
onMessage: ({ kind, text }) => toast(text, { type: kind })
});useTable()
Sort/filters/selection local (URL sync deferido para HOOKS-004 follow-up).
const { sort, setSort, filters, setFilter, selection, toggleSelection, clearSelection } = useTable();useAction(action)
router.visit wrapper com processing flag.
const { invoke, processing } = useAction(action);
<button onClick={() => invoke({ record })} disabled={processing}>...useFieldDependencies()
Debounced 300ms partial reload Inertia de fields.<name>.options.
useFieldDependencies(); // injetado em <FieldRenderer>Triggera quando um field marcado dependsOn(['country']) re-resolve options server-side via Resource.handleDependencyUpdate.
useNavigation()
Lê a shared prop Inertia panel.navigation (populada server-side por HandleArqelInertiaRequests::buildNavigation()).
const { items } = useNavigation();
// items: NavigationItemPayload[]NavigationItemPayload:
type NavigationItemPayload = {
label: string;
url: string;
icon: string | null; // ID lucide-react
group: string | null; // grouping label, null = top-level
sort: number;
active: boolean; // resolvido server-side via current request
};Consumido por <Sidebar> (block shadcn sidebar-07) — items são agrupados por group no render.
useTheme()
Re-exportado de @arqel-dev/theme. Requer <ThemeProvider> na árvore (incluído automaticamente em <ArqelProvider> / createArqelApp). Sem provider, lança erro descritivo.
const { theme, resolved, setTheme, toggle } = useTheme();useBreakpoint()
Tailwind v4 breakpoint via matchMedia. SSR-safe.
const bp = useBreakpoint();
// { current: 'sm' | 'md' | 'lg' | 'xl' | '2xl', isMobile: boolean }useArqelOptimistic()
React 19 useOptimistic wrapper.
const [optimisticPosts, addOptimistic] = useArqelOptimistic(posts, (state, newPost) => [...state, newPost]);Related
- SKILL:
packages-js/hooks/SKILL.md - Próximo:
@arqel-dev/ui