|
| 1 | +# ActionUI Architecture |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +ActionUI renders SwiftUI views from JSON descriptions. There is no intermediate runtime, virtual DOM, or reconciliation step — JSON is parsed into validated properties and constructed directly as SwiftUI views. |
| 6 | + |
| 7 | +## Pipeline |
| 8 | + |
| 9 | +``` |
| 10 | +┌─────────────────────────────────────────────┐ |
| 11 | +│ JSON/Plist Description │ |
| 12 | +│ { "type": "Button", "id": 1, ... } │ |
| 13 | +└─────────────────┬───────────────────────────┘ |
| 14 | + │ |
| 15 | + ▼ |
| 16 | +┌─────────────────────────────────────────────┐ |
| 17 | +│ ActionUIRegistry │ |
| 18 | +│ - View type registration │ |
| 19 | +│ - Type lookup and dispatch │ |
| 20 | +└─────────────────┬───────────────────────────┘ |
| 21 | + │ |
| 22 | + ▼ |
| 23 | +┌─────────────────────────────────────────────┐ |
| 24 | +│ ActionUIViewConstruction │ |
| 25 | +│ - validateProperties() │ |
| 26 | +│ - buildView() │ |
| 27 | +│ - applyModifiers() │ |
| 28 | +└─────────────────┬───────────────────────────┘ |
| 29 | + │ |
| 30 | + ▼ |
| 31 | +┌─────────────────────────────────────────────┐ |
| 32 | +│ ActionUIModel │ |
| 33 | +│ - State management (@MainActor) │ |
| 34 | +│ - Action routing │ |
| 35 | +│ - View value get/set │ |
| 36 | +└─────────────────────────────────────────────┘ |
| 37 | +``` |
| 38 | + |
| 39 | +### ActionUIRegistry |
| 40 | +Maps type strings ("Button", "TextField", etc.) to view construction implementations. Extensible — new view types are registered here. |
| 41 | + |
| 42 | +### ActionUIViewConstruction Protocol |
| 43 | +Every view type conforms to this protocol, implementing three methods: |
| 44 | +- **validateProperties()** — Validates JSON properties, applies defaults, reports errors/warnings |
| 45 | +- **buildView()** — Constructs the SwiftUI view from validated properties |
| 46 | +- **applyModifiers()** — Applies styling and behavior modifiers (padding, frame, font, actionID, etc.) |
| 47 | + |
| 48 | +### ActionUIModel |
| 49 | +The central state manager. Holds view values, routes action callbacks, and provides the get/set API for client code to read and update view state. |
| 50 | + |
| 51 | +## Supported Components (50+) |
| 52 | + |
| 53 | +**Layout & Containers:** |
| 54 | +HStack, VStack, ZStack, LazyHStack, LazyVStack, LazyHGrid, LazyVGrid, Grid, NavigationStack, NavigationSplitView, NavigationLink, TabView, Group, Section, Form, ControlGroup, DisclosureGroup, GroupBox, ScrollView, ScrollViewReader |
| 55 | + |
| 56 | +**Input Controls:** |
| 57 | +TextField, SecureField, TextEditor, Picker, ComboBox, DatePicker, ColorPicker, Toggle, Slider, Button, Link, ShareLink, Menu |
| 58 | + |
| 59 | +**Display Elements:** |
| 60 | +Text, Label, Image, AsyncImage, ProgressView, Gauge, Table, List, VideoPlayer, Map, Canvas, WebView, Spacer, Divider, EmptyView |
| 61 | + |
| 62 | +**Dynamic Loading:** |
| 63 | +LoadableView — Load JSON UI definitions at runtime from files or URLs |
| 64 | + |
| 65 | +## Universal Modifiers |
| 66 | + |
| 67 | +All views inherit modifiers from the base View implementation: |
| 68 | +- **Layout:** padding, frame, background, cornerRadius, position, offset |
| 69 | +- **Styling:** foregroundColor, font, opacity, shadow, border |
| 70 | +- **Sizing:** controlSize (mini, small, regular, large, extraLarge) |
| 71 | +- **Behavior:** hidden, disabled, actionID, keyboardShortcut |
| 72 | +- **Accessibility:** accessibilityLabel, accessibilityHint |
| 73 | + |
| 74 | +## State Management |
| 75 | + |
| 76 | +Views with integer IDs have their state tracked by ActionUIModel. Client code can: |
| 77 | +- **Get values:** Read the current value of any identified view |
| 78 | +- **Set values:** Update view values programmatically |
| 79 | +- **Get/set properties:** Read or modify view properties at runtime |
| 80 | +- **Get/set state:** Access view-specific state (e.g., scroll position) |
| 81 | + |
| 82 | +## Action System |
| 83 | + |
| 84 | +User interactions fire action callbacks identified by string IDs. The action handler receives: |
| 85 | +- **actionID** — The string identifier from the view's JSON |
| 86 | +- **windowUUID** — Which window the action originated from |
| 87 | +- **viewID** — The integer ID of the view |
| 88 | +- **viewPartID** — Sub-component identifier (e.g., column index in a table) |
| 89 | +- **context** — Optional contextual data (e.g., button title, row index) |
| 90 | + |
| 91 | +## Language Adapters |
| 92 | + |
| 93 | +ActionUI's core is a Swift framework. Language adapters provide bindings for different programming environments: |
| 94 | + |
| 95 | +- **ActionUISwiftAdapter** — Native Swift integration |
| 96 | +- **ActionUIObjCAdapter** — Objective-C bridging |
| 97 | +- **ActionUICAdapter** — C function API (foundation for other language bindings) |
| 98 | +- **ActionUICppAdapter** — C++ bindings |
| 99 | +- **ActionUIJavaScriptCoreAdapter** — JavaScriptCore integration |
| 100 | +- **ActionUIWebKitJSAdapter** — WebKit JavaScript bridge |
| 101 | +- **ActionUI Python Module** — Full Python package with pip install (see [Python Bridge](#python-bridge)) |
| 102 | + |
| 103 | +## Python Bridge |
| 104 | + |
| 105 | +The `actionui` Python module provides a complete API for building macOS applications: |
| 106 | + |
| 107 | +```python |
| 108 | +import actionui |
| 109 | + |
| 110 | +app = actionui.Application(name="MyApp") |
| 111 | + |
| 112 | +window = actionui.Window.from_file("ui.json", title="My Window") |
| 113 | +app.load_and_present_window(window) |
| 114 | + |
| 115 | +@app.action("buttonClicked") |
| 116 | +def on_button(ctx): |
| 117 | + value = window.get_string(view_id=10) |
| 118 | + window.set_string(view_id=20, value=f"You entered: {value}") |
| 119 | + |
| 120 | +app.run() |
| 121 | +``` |
| 122 | + |
| 123 | +### Application Features |
| 124 | +- Multi-window management with per-window state |
| 125 | +- Application lifecycle callbacks (will_terminate, should_terminate, etc.) |
| 126 | +- Window lifecycle callbacks (window_will_present, window_will_close) |
| 127 | +- Native menu bar with CommandGroup and CommandMenu |
| 128 | +- File open/save panels with type filtering |
| 129 | +- Alert dialogs with custom buttons |
| 130 | + |
| 131 | +### Building |
| 132 | +The Python module is built from `ActionUIPython/` using `build_and_install.sh`, which: |
| 133 | +1. Builds ActionUI static frameworks via xcodebuild (universal arm64 + x86_64) |
| 134 | +2. Compiles the C bridge (`actionui_native.m`) against the frameworks |
| 135 | +3. Installs the `actionui` Python package via pip |
| 136 | + |
| 137 | +## Platform Support |
| 138 | + |
| 139 | +- macOS 14.6+ |
| 140 | +- iOS 17.6+ |
| 141 | +- iPadOS 17.6+ |
| 142 | +- watchOS 10.6+ |
| 143 | +- tvOS 17.6+ |
| 144 | +- visionOS 2.6+ |
| 145 | + |
| 146 | +Platform-specific views (e.g., Table on macOS) are conditionally available. Unsupported features degrade gracefully with validation warnings. |
| 147 | + |
| 148 | +## Tools |
| 149 | + |
| 150 | +- **ActionUIViewer** — Preview JSON files, take screenshots for sharing or AI feedback |
| 151 | +- **ActionUIVerifier** — Validate JSON files before deployment |
| 152 | +- **ActionUISwiftTestApp** — Test app with examples of all supported view types |
0 commit comments