Dala.Plugin (dala v0.0.10)

Copy Markdown View Source

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

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

This is NOT UI code. This is metadata.

Core Dala automatically generates:

  • Protocol encoders/decoders
  • Validators
  • Documentation
  • Registry entries

Plugin Package Structure

my_plugin/
  lib/
      my_plugin.ex          # Plugin schema definitions
  native/
      rust/                 # Rust NIF extensions (optional)
      ios/                  # iOS native views
      android/              # Android native views
  protocol/                  # Generated binary protocol
  assets/                    # Static assets

Schema-First Architecture

Designing around schema-first (not widget-first, not native-view-first, not protocol-first) unlocks:

  • Tooling and validation
  • Code generation
  • Compatibility guarantees
  • Visual editors
  • Plugin ecosystems
  • AI-generated UIs
  • Hot reload
  • Documentation

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.

Summary

Functions

Macro callback - registers the plugin after module compilation.

Defines a new plugin module.

Auto-registers all plugins found in loaded applications.

Defines a new component within the plugin.

Sets the native API version.

Sets the binary protocol version.

Sets the plugin schema version.

Types

capability()

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

component_name()

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

event_name()

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

plugin_name()

@type plugin_name() :: atom()

prop_name()

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

prop_type()

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

Functions

__before_compile__(env)

(macro)

Macro callback - registers the plugin after module compilation.

__using__(opts \\ [])

(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")

auto_register()

Auto-registers all plugins found in loaded applications.

component(name, list)

(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

native_api_version(version)

(macro)

Sets the native API version.

protocol_version(version)

(macro)

Sets the binary protocol version.

schema_version(version)

(macro)

Sets the plugin schema version.