-
Notifications
You must be signed in to change notification settings - Fork 14
Register/ Render custom component #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sanyamkamat
merged 12 commits into
BuilderIO:main
from
aarondemelo:feat/custom_component
Jul 9, 2025
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
ae1e055
initial commit for custom components
aarondemelo ddd1dfd
ability to register custom components for rendering which have been p…
aarondemelo 9cbbdd2
formatted code
aarondemelo c1d6d85
Simplified component registry
aarondemelo a5dd59a
added notification to update in appetize
aarondemelo 42f7bc9
added new protocol for custom components needing registration in the …
aarondemelo ec9f11b
refactored registration workflow
aarondemelo f6d410f
code cleanup
aarondemelo 2786094
updated readme
aarondemelo 53fa6d9
Added support for center align boxes
aarondemelo 3b792e4
added support to render backgrounds for empty boxes
aarondemelo ccf40c3
updated readme
aarondemelo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,95 +1,167 @@ | ||
| # BuilderIO-Swift | ||
|
|
||
| The SDK for BuilderIO for iOS in Swift. | ||
| The official Swift SDK to render Builder.io content in your iOS app using SwiftUI. | ||
|
|
||
| ## Using this SDK | ||
|
|
||
| ### Add dependency | ||
| ### iOS Compatibility | ||
|
|
||
| * Add a dependency on the Builder Swift SDK in your iOS App via the Github package: https://github.com/BuilderIO/builder-swift | ||
| * Point to the `main` branch of the repository to get the latest and greatest SDK code | ||
| * Import `BuilderIO` wherever you need to use the SDK methods | ||
| This SDK supports **iOS 17 and above** to take advantage of the latest SwiftUI capabilities and improved layout behaviors. | ||
|
|
||
| ### (Optional) Register your custom components | ||
|
|
||
| Register any components you have created in your iOS App using something like | ||
| ### Add Dependency | ||
|
|
||
| ``` | ||
| ###TODO | ||
| ``` | ||
| To integrate the Builder Swift SDK into your iOS App: | ||
|
|
||
| ## Render Content | ||
| 1. Add a dependency using the GitHub repository: | ||
| [https://github.com/BuilderIO/builder-swift](https://github.com/BuilderIO/builder-swift) | ||
|
|
||
| At the location where you want to render the content fetched from Builder | ||
| 2. Point to the `main` branch to always receive the latest SDK updates. | ||
|
|
||
| For a standalone page instantiate | ||
| 3. Import the SDK wherever you need to access its functionality: | ||
|
|
||
| ```swift | ||
| import BuilderIO | ||
| ``` | ||
| --- | ||
|
|
||
| ### Render Content | ||
|
|
||
| #### Render a Full Page | ||
|
|
||
| Use `BuilderIOPage` to render a full page from a given Builder URL: | ||
|
|
||
| ```swift | ||
| BuilderIOPage(apiKey: "<YOUR_BUILDER_API_KEY>", url: "/YOUR_TARGET_URL") | ||
| ``` | ||
| In the above, model is optional set to `page` (add if the model you used is not the default page model in Builder) | ||
|
|
||
| eg | ||
| ``` | ||
| ###### Example: | ||
|
|
||
| ```swift | ||
| var body: some View { | ||
| NavigationStack { | ||
| BuilderIOPage(apiKey: "<YOUR_BUILDER_API_KEY>", url: "/YOUR_TARGET_URL") | ||
| } | ||
| NavigationStack { | ||
| BuilderIOPage(apiKey: "<YOUR_BUILDER_API_KEY>", url: "/YOUR_TARGET_URL") | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| For a section instantiate | ||
| ``` | ||
| BuilderIOSection(apiKey: "<YOUR_BUILDER_API_KEY>", model: "YOUR_MODEL_NAME") | ||
| ``` | ||
| eg | ||
| You can optionally specify the `model` if you're not using the default `"page"` model. | ||
|
|
||
| --- | ||
|
|
||
| #### Render a Section | ||
|
|
||
| Use `BuilderIOSection` to render content meant to be embedded in an existing layout: | ||
|
|
||
| ```swift | ||
| BuilderIOSection(apiKey: "<YOUR_BUILDER_API_KEY>", model: "YOUR_MODEL_NAME") | ||
| ``` | ||
|
|
||
| ##### Example: | ||
|
|
||
| ```swift | ||
| VStack { | ||
| BuilderIOSection(apiKey: "<YOUR_BUILDER_API_KEY>", model: "YOUR_MODEL_NAME") | ||
| } | ||
| BuilderIOSection(apiKey: "<YOUR_BUILDER_API_KEY>", model: "YOUR_MODEL_NAME") | ||
| } | ||
| ``` | ||
|
|
||
| Alternatively, if you want to override the click handling and want to intercept each `Button` click, then you register the environment buttonActionManager for open links and setHandler for custom actions | ||
| --- | ||
|
|
||
| ``` | ||
| BuilderIOPage(apiKey: "<YOUR_BUILDER_API_KEY>", url: "/YOUR_TARGET_URL").environment(\.buttonActionManager, buttonActionManager) | ||
| .onAppear { | ||
| buttonActionManager.setHandler { builderAction in | ||
| print("Handle Event Action") | ||
| } | ||
| } | ||
| ### Custom Click Handling | ||
|
|
||
| To intercept and handle clicks (e.g., for `button` components), you can override the default behavior using `buttonActionManager`: | ||
|
|
||
| ```swift | ||
| BuilderIOPage(apiKey: "<YOUR_BUILDER_API_KEY>", url: "/YOUR_TARGET_URL") | ||
| .environment(\.buttonActionManager, buttonActionManager) | ||
| .onAppear { | ||
| buttonActionManager.setHandler { builderAction in | ||
| // Handle your custom action here | ||
| print("Custom Action Triggered: \(builderAction)") | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Fetch Content | ||
| ### (Optional) Register Custom Components | ||
|
|
||
| Based on needs request to raw model data can be gathered by instantiating BuilderIOManager with your API key and requesting the your required model /URL | ||
| You can register your own custom SwiftUI views to be rendered by Builder using: | ||
|
|
||
| ```swift | ||
| BuilderComponentRegistry.shared.registerCustomComponent( | ||
| componentView: MyCustomComponent.self, | ||
| apiKey: "<YOUR_BUILDER_API_KEY>" | ||
| ) | ||
| ``` | ||
| BuilderIOManager(apiKey:"<YOUR_BUILDER_API_KEY>").fetchBuilderContent(model: String = "YOUR_MODEL_NAME", url: String? = "/YOUR_TARGET_URL") | ||
|
|
||
| > Replace `MyCustomComponent` with the name of your custom SwiftUI view. | ||
|
|
||
| Custom components **must conform** to the `BuilderCustomComponentViewProtocol`. | ||
|
|
||
| --- | ||
|
|
||
| To enable live editing and previewing of your custom components inside the [Builder.io Visual Editor](https://www.builder.io/): | ||
|
|
||
| 1. Upload a **simulator build** of your app to [Appetize.io](https://appetize.io). | ||
| 2. Link your **Appetize build ID** in your Builder.io space under **Connected Devices**. | ||
| 3. Once your Builder.io page loads inside the Appetize-hosted simulator, the component registration will be completed automatically. | ||
|
|
||
| This setup enables **real-time editing** and **custom component preview** within Builder’s visual editor. | ||
|
|
||
| --- | ||
|
|
||
| #### Handle Preview Updates from the WebApp | ||
|
|
||
| To handle live preview updates: | ||
|
|
||
| - Ensure your app is uploaded to **Appetize.io** and **linked** to your Builder.io space. | ||
| - Builder.io pushes content updates to the app running in Appetize, allowing you to see changes immediately as you edit. | ||
|
|
||
| This supports a **live editing workflow** without the need for rebuilding or redeploying your app for every update. | ||
|
|
||
| --- | ||
|
|
||
| ### Fetch Content (Raw Data) | ||
|
|
||
| To fetch Builder content manually (e.g., for preview, caching, or custom rendering), use: | ||
|
|
||
| ```swift | ||
| BuilderIOManager(apiKey: "<YOUR_BUILDER_API_KEY>") | ||
| .fetchBuilderContent(model: "YOUR_MODEL_NAME", url: "/YOUR_TARGET_URL") | ||
| ``` | ||
|
|
||
| This returns the raw JSON or decoded model data from Builder. | ||
|
|
||
| --- | ||
|
|
||
|
|
||
| ## Complete Example | ||
|
|
||
| https://github.com/aarondemelo/BuilderIOExample | ||
|
|
||
| --- | ||
|
|
||
| ## Handle Preview Updates from the WebApp | ||
| ## Current Support | ||
|
|
||
| ###TODO | ||
| | Builder Component | Color | Margin / Padding | Horizontal Alignment | Click Support | Unsupported Features | | ||
| |-----------------------|:-----:|:-----------------:|:----------------------:|:--------------:| | ||
| | **Button** | ✅ | ✅ | ✅ | ✅ | | ||
| | **Text** | ✅ | ✅ | ✅ | ✅ | | ||
| | **Image** | ✅ | ✅ | ✅ | ✅ | Image Position, Lock Aspect Ratio | ||
| | **Columns** | ✅ | ✅ | ✅ | ✅ | | ||
| | **Sections** | ✅ | ✅ | ✅ | ✅ | Lazy Load | ||
| | **Custom** | ✅ | ✅ | ✅ | ✅ | | ||
| | **Video** | 🏗 | 🏗 | 🏗 | 🏗 | | ||
|
|
||
| ## Complete example | ||
|
|
||
| For a complete example of an iOS app using the Builder SDK, please refer to ###TODO | ||
| You can use this as a base app, and replace the API key in the example with your own to try it out. | ||
| **Unsupported** | ||
| JS Code Execution, Data Binding, API Data | ||
|
|
||
| ## Current Support: | ||
| --- | ||
|
|
||
| #### Unsupported in Layouts | ||
| - Grid Layout with variable sized components | ||
|
|
||
| | Builder Component|Color|Margin / Padding|Horizontal Alignment|Click Support| | ||
| |------------------|-----|----------------|--------------------|-------------| | ||
| | Button | ✅ | ✅ | ✅ | ✅ | | ||
| | Text | ✅ | ✅ | ✅ | ✅ | | ||
| | Image | ✅ | ✅ | ✅ | ✅ | | ||
| | Columns | ✅ | ✅ | ✅ | ✅ | | ||
| | Video | 🏗 | 🏗 | 🏗 | 🏗 | | ||
|
|
||
| ## Contributing |
12 changes: 8 additions & 4 deletions
12
Sources/BuilderIO/ComponentRegistry/BuilderComponentProtocol.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why have these been made static?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static to make it visible externally during registration without the need to repeat the type instantiation.
eg. for the internal component registration workflow
It enables easier custom component registration
componentView: RatingsComponent.self, apiKey: "###############")
which internally performs registry[componentView.componentType] = componentView