Adapters

The core of Gridla is a set of pure functions over plain objects. An adapter binds that core to a rendering model: it measures the canvas, positions items, turns pointer and keyboard input into solver calls, and hands the committed layout back to your state. Every adapter ships from the same gridla package as its own subpath export, with the framework as an optional peer dependency and nothing else.

Appearance is always yours: the styling guide lists every data-gridla-* attribute and shows how to style items, handles, and the preview outline once for all of them.

Overview

FrameworkEntryStatusGuide
Reactgridla/reactAvailableReact quickstart
DOM (vanilla)gridla/domAvailableDOM
Web Componentsgridla/elementsAvailableWeb Components
Vuegridla/vueAvailableVue
Sveltegridla/svelteAvailableSvelte
Solidgridla/solidAvailableSolid
Angulargridla/angularAvailableAngular
Qwikgridla/qwikAvailableQwik
Preactgridla/reactAvailablePreact

Preact reuses the React adapter through preact/compat; the Preact page documents the alias setup and the verification that runs against it in the package contract suite.

Which one?

Pick the entry for the framework that renders your page; the layout behaves the same in every one of them, and the core stays available for solving outside a component tree. Without a framework, use gridla/dom when you mount from code (one function, one element) and gridla/elements when you declare the canvas in HTML or from a template engine. Mixing adapters on one page is fine; they share no global state.

Shared contract

Adapters share a contract so that switching frameworks, or mixing them on one page, changes nothing about how a layout behaves. The React adapter defines the reference behavior; every guide above has the same sections (install, minimal example, controlled and uncontrolled, nested layouts and transfers, server rendering, API) so the differences are easy to find.

  • Same names. GridProvider (or the framework's idiom for it: mountGrid in the DOM, <gridla-canvas> as a custom element, [gridlaProvider] in Angular), GridCanvas, GridItem, GridPreviewOutline, and GridTransferScope.
  • Same props. Controlled (layout plus onLayoutChange) and uncontrolled (defaultLayout) modes, responsive, config or the individual SolveOptions fields (gap, snapDistance, snap, onTrace), selectedId, acceptTransfers, onTransferIn, onTransferOut, onCommit, and onItemClick. Change callbacks receive the next layout and a GridChangeDetail (reason, itemId, solver strategy). Frameworks spell the binding their own way (v-model:layout, bind:layout, [(layout)], onLayoutChange$), but the semantics do not change.
  • Same data attributes. Every adapter marks the canvas with data-gridla-canvas, each item with data-gridla-item="<id>", the active, selected, shifted, and transferring items with data-gridla-active, data-gridla-selected, data-gridla-shifted, and data-gridla-transferring, the landing box with data-gridla-preview, and handles with data-gridla-drag-handle, data-gridla-resize-handle (the item id), and data-gridla-edge="<edge>". The root carries data-gridla-dragging while a gesture runs. Styles, tests, and tooling written against one adapter work against all of them.
  • Headless. Adapters position items (transform by default, or left/top with positioning: 'absolute') and nothing more. No stylesheet ships; theming is yours.
  • Server rendering. No window or document access at import time. The server output is the authored layout; on the client the canvas measures itself before the first paint where the framework allows it, so the projected layout is what the user sees first.
  • Nested layouts and transfer scope. Nested canvases are nested providers, and items move between canvases through a transfer scope: the pointer decides the target, the target previews the drop, and releasing commits it, exactly as in the transfer recipe.

Write your own adapter

All adapters are thin bindings over gridla/interaction, the framework-neutral layer the React adapter is built on. It is a public entry, so an adapter for a framework not listed here is a small module rather than a reimplementation. The four functions to know:

  • createGridController owns the store, the projection onto the measured size, the gesture API, the controlled and uncontrolled sync, and the onLayoutChange reasons. Your adapter renders store snapshots and forwards prop changes with setLayout, setSize, and setConfig.
  • createPointerGesture turns pointer and keyboard input into controller calls. It takes a minimal event shape, so it works with synthetic events too; bindPointer(element) attaches native listeners and returns an unsubscribe.
  • createTransferScope registers controllers and hit-tests their canvases during a drag, so several providers (from any adapter) can exchange items.
  • observeSize measures an element synchronously and then through ResizeObserver, which is how every adapter feeds setSize.

Emit the data attributes above from GRID_DATA, keep your module free of window and document at import time, and the shared browser contract suite can run against your demo app unchanged.

Verification

Each adapter is exercised three ways: unit tests against the framework's own test utilities, the shared browser contract suite that runs the same scenarios against a small demo app per adapter, and the package contract suite that installs the packed tarball into a consumer project for that framework. The demo apps are published with the documentation site under /adapters/<name>/.