# `Dala.Plugin`
[🔗](https://github.com/manhvu/dala/blob/main/lib/dala/plugin.ex#L1)

Behaviour and macros for self-describing component plugins.

Plugins declare themselves declaratively, allowing Dala core to remain generic.
Everything becomes a plugin: video, maps, charts, camera, ML views, custom renderers, AR, etc.

## Architecture

Dala core knows almost nothing. Plugins self-describe through:

- **Schema** - component metadata (props, events, capabilities)
- **Protocol** - binary communication format (auto-generated)
- **Native renderer** - platform-specific implementation (iOS/Android)

This is the same pattern used by:
- React Native Fabric
- Flutter Engine
- SwiftUI internals
- Jetpack Compose runtime
- VSCode extension host
- Browser DOM

## Example (top-level DSL)

    defmodule MyApp.VideoPlugin do
      use Dala.Plugin

      component "video" do
        prop "source", :string
        prop "autoplay", :bool
        prop "controls", :bool
        prop "volume", :f32

        event "progress"
        event "ended"
        event "ready"

        native "ios", "DalaVideoView"
        native "android", "com.dala.video.VideoView"

        capability :gestures
        capability :accessibility
        capability :animation
      end
    end

## Example (plugin do block)

    defmodule MyApp.VideoPlugin do
      use Dala.Plugin

      plugin do
        plugin_description "Video playback plugin"

        component "video", MyApp.VideoComponent
        plugin_event "video_zoom", MyApp.Video.Events.Zoom

        plugin_native :ios, MyApp.Video.IOS
        plugin_native :android, MyApp.Video.Android

        plugin_permission :camera
        plugin_dependency {:maps, "~> 1.0"}
        plugin_platform :ios
        plugin_platform :android
      end
    end

## Behaviour

Modules using `Dala.Plugin` must implement (or get defaults for) these callbacks:

- `init(opts)` → `{:ok, state}` | `{:error, reason}` — resource allocation (required)
- `components()` → `[Component.t()]` — declare components (required)
- `capabilities()` → `[atom()]` — what this plugin provides (required)
- `permissions()` → `[atom()]` — declare required permissions (optional, default `[]`)
- `native_modules(platform)` → `[module()]` — platform-specific native modules (optional, default `[]`)
- `dependencies()` → `[{atom(), String.t()}]` — dependency ordering (optional, default `[]`)
- `validate_config(config)` → `:ok` | `{:error, reason}` — compile-time hooks (optional, default `:ok`)
- `handle_event(event, payload, state)` → `{:ok, state}` | `{:error, reason}` — runtime hooks (optional, default `{:ok, state}`)
- `cleanup(state)` → `:ok` — resource deallocation / hot reload (optional, default `:ok`)

## Versioning

Plugins MUST declare versions for compatibility:

    schema_version "1.0.0"
    protocol_version 3
    native_api_version "2.0.0"

This prevents ecosystem fragmentation.

## Host/Runtime Separation

Plugins should NEVER directly access:

- BEAM internals
- Scheduler state
- Raw protocol sockets

Instead:

    Plugin
       ↓
    Host API
       ↓
    Dala Runtime

Exactly like browser extensions.

## Generic Node Model

Everything becomes a generic node:

    %Dala.Node{
      type: "video",
      props: %{source: "...", autoplay: true},
      children: []
    }

Dala core NEVER special-cases video, maps, or charts.
The same generic lifecycle applies to all plugins:

- create/2
- update/2
- layout/2
- event/3
- dispose/1

Optional capabilities:
- animate/2
- focus/2
- accessibility/2
- snapshot/1
- texture/1
- gesture/2

## Universal Command Stream

Dala core emits only generic operations:

- CREATE_NODE
- UPDATE_PROP
- REMOVE_NODE
- EMIT_EVENT
- RUN_ANIMATION

Plugins interpret semantics. Core stays tiny.

# `capability`

```elixir
@type capability() ::
  :gestures
  | :accessibility
  | :animation
  | :textures
  | :overlay
  | :clipping
  | :touch
  | :keyboard
  | :focus
```

# `component_name`

```elixir
@type component_name() :: String.t()
```

# `event_name`

```elixir
@type event_name() :: String.t()
```

# `platform`

```elixir
@type platform() :: :ios | :android | :web
```

# `plugin_name`

```elixir
@type plugin_name() :: atom()
```

# `prop_name`

```elixir
@type prop_name() :: String.t()
```

# `prop_type`

```elixir
@type prop_type() ::
  :string
  | :bool
  | :integer
  | :float
  | :f32
  | :f64
  | :color
  | :binary
  | :list
  | :map
```

# `status`

```elixir
@type status() :: :registered | :initialized | :active | :error | :unloaded
```

# `capabilities`

```elixir
@callback capabilities() :: [atom()]
```

Returns the list of capabilities this plugin provides.

# `cleanup`

```elixir
@callback cleanup(state :: term()) :: :ok
```

Cleans up resources before hot reload or unload.

# `components`

```elixir
@callback components() :: [Dala.Plugin.Component.t()]
```

Returns the list of component schemas this plugin provides.

# `dependencies`

```elixir
@callback dependencies() :: [{atom(), String.t()}]
```

Returns dependency specifications: `{plugin_name, version_requirement}`.

# `handle_event`

```elixir
@callback handle_event(event :: atom(), payload :: map(), state :: term()) ::
  {:ok, state :: term()} | {:error, reason :: term()}
```

Handles runtime events sent to the plugin.

# `init`

```elixir
@callback init(opts :: keyword()) :: {:ok, state :: term()} | {:error, reason :: term()}
```

Initializes the plugin. Allocates resources, starts processes, etc.
Returns `{:ok, state}` on success or `{:error, reason}` on failure.

# `native_modules`

```elixir
@callback native_modules(platform :: platform()) :: [module()]
```

Returns platform-specific native modules for the given platform.

# `permissions`

```elixir
@callback permissions() :: [atom()]
```

Returns the list of permissions this plugin requires.

# `validate_config`

```elixir
@callback validate_config(config :: map()) :: :ok | {:error, reason :: term()}
```

Validates plugin configuration at compile-time.

# `__before_compile__`
*macro* 

Macro callback - builds the full plugin struct and generates default
behaviour implementations.

# `__using__`
*macro* 

Defines a new plugin module.

## Options

  * `:schema_version` - Plugin schema version (default: "1.0.0")
  * `:protocol_version` - Binary protocol version (default: 3)
  * `:native_api_version` - Native API version (default: "2.0.0")
  * `:platforms` - List of supported platforms (e.g. [:ios, :android])
  * `:capabilities` - List of plugin-level capabilities
  * `:dala_requires` - Dala version requirement string
  * `:metadata` - Arbitrary metadata map

# `auto_register`

Auto-registers all plugins found in loaded applications.

# `component`
*macro* 

Defines a new component within the plugin.

## Example

    component "video" do
      prop "source", :string
      prop "autoplay", :bool
      prop "volume", :f32

      event "progress"
      event "ended"

      native "ios", "DalaVideoView"
      native "android", "com.dala.video.VideoView"

      capability :gestures
      capability :accessibility
    end

# `dependency`
*macro* 

Declares a dependency on another plugin with a version requirement.

# `description`
*macro* 

Sets the plugin description.

# `native_api_version`
*macro* 

Sets the native API version.

# `native_module`
*macro* 

Declares a native module for a specific platform.

# `permission`
*macro* 

Declares a permission the plugin requires.

# `platform`
*macro* 

Declares platform support.

# `plugin`
*macro* 

Main entry point for the plugin DSL block.

Inside a `plugin do` block, you can declare:

- `component :chart, MyPlugin.ChartComponent`
- `plugin_event :chart_zoom, MyPlugin.Events.Zoom`
- `plugin_native :ios, MyPlugin.IOS`
- `plugin_native :android, MyPlugin.Android`
- `plugin_permission :camera`
- `plugin_dependency {:maps, "~> 1.0"}`
- `plugin_platform :ios`
- `plugin_platform :android`
- `plugin_description "My chart plugin"`

If `plugin do` is used, it takes precedence for those declarations.

# `protocol_version`
*macro* 

Sets the binary protocol version.

# `schema_version`
*macro* 

Sets the plugin schema version.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
