<!-- Skal docs — markdown mirror of https://skal.run/docs/native.html -->

# Wrapping pub.dev packages

The point of rendering with Flutter isn't just pixels — it's [pub.dev](https://pub.dev): tens of thousands of maintained native plugins. Skal's codegen turns any Flutter widget into a JSX component.

## One line of config

List the package in your app's `skal_codegen.yaml`:

```jsx
# flutter-host/lib/skal_codegen.yaml
packages:
  - qr_flutter
  - shimmer
  - camera
```

Then run the generator:

```jsx
$ bun run codegen
```

The builder introspects each package's public widgets with Dart's analyzer — constructors, named constructors, parameter types — and emits adapters that register them with Skal's widget registry. On the JS side, typed components appear under `skal-flutter`:

```jsx
import { QrImageView, ShimmerFromColors, Camera } from 'skal-flutter';

<QrImageView data="https://skal.dev" size={220} />

<ShimmerFromColors baseColor="#FF1F2937" highlightColor="#FF374151">
  <Box width="fill" height={96} cornerRadius={12} />
</ShimmerFromColors>
```

Named constructors surface as their own components — shimmer's `Shimmer.fromColors` becomes `<ShimmerFromColors>`. Prop types round-trip: enums, colors, durations, edge insets.

## Calling native APIs (not just widgets)

Plugins with imperative APIs — geolocation, biometrics, file pickers — ship as shim packages with one async JS surface:

```jsx
import { getCurrentPosition } from 'skal-plugin-geolocator';

const pos = await getCurrentPosition();
// { lat, lon, accuracy, altitude, speed, timestamp }
```

On web this routes through the hidden Flutter plugin host today; the native routing for the same calls is in progress. Imperative _native_ work is done today through host-widget RPC: bind a `ref`, then `await ref.method(args)` — one RPC op out, the reply back through the reply heap, and Dart `Stream`s subscribe via `ref.name$(cb)`. The Camera and Ticker demos in kitchen-sink use exactly this.

## Custom Dart widgets

Your own Flutter widgets register the same way — a small adapter reads props off the node and returns your widget:

```jsx
// flutter-host/lib/adapters/gauge.dart
Widget _buildGauge(NodeState n, SkalBridge bridge) =>
    Gauge(value: n.getCustomPropF32('value', 0));

SkalRegistry.registerWidget('gauge', _buildGauge);
// <Gauge value={0.7} /> is now available in JSX
```

For full control (custom prop decoding, children handling, RPC methods), the generated adapters in `lib/adapters/generated/` are the documentation for the shape.

## When codegen isn't enough

-   **Function-valued parameters** (builders, custom painters) can't cross the bridge declaratively — wrap those widgets manually with a constrained prop surface.
-   **Web target:** plugin calls route through a headless Flutter Web instance, so the same shim API works in the browser for plugins with web implementations.

[Previous← State & the Store](state.html) [NextHot reload & dev loop →](tooling.html)
