@rdlabo/capacitor-native-ui 1.2.1 → 2.0.0-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -24
- package/dist/core.d.ts +2 -2
- package/dist/native/activation.d.ts.map +1 -1
- package/dist/native/activation.js +19 -19
- package/dist/native/activation.js.map +1 -1
- package/dist/native/definitions.d.ts +22 -40
- package/dist/native/definitions.d.ts.map +1 -1
- package/dist/native/html.d.ts.map +1 -1
- package/dist/native/html.js +10 -1
- package/dist/native/html.js.map +1 -1
- package/dist/native/index.d.ts +2 -2
- package/dist/native/index.d.ts.map +1 -1
- package/dist/native/index.js +2 -11
- package/dist/native/index.js.map +1 -1
- package/dist/native/overlays/controller.js +1 -1
- package/dist/native/overlays/controller.js.map +1 -1
- package/dist/native/prehide.js +1 -1
- package/dist/native/prehide.js.map +1 -1
- package/dist/native/runtime.d.ts +1 -1
- package/dist/native/runtime.d.ts.map +1 -1
- package/dist/native/runtime.js +8 -20
- package/dist/native/runtime.js.map +1 -1
- package/dist/native/shared/candidate.d.ts +2 -2
- package/dist/native/shared/candidate.d.ts.map +1 -1
- package/dist/native/shared/candidate.js +2 -2
- package/dist/native/shared/candidate.js.map +1 -1
- package/dist/native/shared/control-options.d.ts +6 -0
- package/dist/native/shared/control-options.d.ts.map +1 -0
- package/dist/native/shared/control-options.js +17 -0
- package/dist/native/shared/control-options.js.map +1 -0
- package/dist/native/shared/toolbar-options.d.ts +6 -2
- package/dist/native/shared/toolbar-options.d.ts.map +1 -1
- package/dist/native/shared/toolbar-options.js +7 -15
- package/dist/native/shared/toolbar-options.js.map +1 -1
- package/dist/native/startup.d.ts.map +1 -1
- package/dist/native/startup.js +0 -16
- package/dist/native/startup.js.map +1 -1
- package/dist/native/vertical-bars-web.d.ts.map +1 -1
- package/dist/native/vertical-bars-web.js +3 -2
- package/dist/native/vertical-bars-web.js.map +1 -1
- package/dist/vertical-bars.d.ts +2 -2
- package/docs/appearance.md +45 -0
- package/docs/configuration.md +106 -74
- package/docs/framework-independent.md +52 -13
- package/docs/ionic-vertical-bars.md +186 -0
- package/docs/migration.md +67 -89
- package/docs/native-ui-extensions.md +61 -32
- package/docs/native-ui.md +187 -68
- package/docs/setup.md +46 -25
- package/docs/vertical-bars.md +118 -79
- package/ios/Sources/NativeUIPlugin/NativeUIPlugin.swift +1 -1
- package/package.json +1 -1
- package/src/core.ts +1 -2
- package/src/native/activation.ts +13 -22
- package/src/native/definitions.ts +40 -90
- package/src/native/html.ts +11 -5
- package/src/native/index.ts +2 -11
- package/src/native/overlays/controller.ts +1 -1
- package/src/native/prehide.ts +1 -1
- package/src/native/runtime.ts +7 -16
- package/src/native/shared/candidate.ts +4 -4
- package/src/native/shared/control-options.ts +20 -0
- package/src/native/shared/toolbar-options.ts +8 -12
- package/src/native/startup.ts +0 -16
- package/src/native/vertical-bars-web.ts +4 -2
- package/src/vertical-bars.ts +2 -1
- package/docs/native-mini-player.md +0 -47
|
@@ -6,16 +6,16 @@ title: App-local Native UI extensions (experimental)
|
|
|
6
6
|
|
|
7
7
|
> **Experimental:** The extension API, native registration interfaces and behavior may change in future releases. This applies to both SwiftUI and Kotlin/Compose extensions, including `element` and `tab-accessory` placement.
|
|
8
8
|
|
|
9
|
-
> This guide targets the upcoming package split. Until the first native package release, use the [candidate archive installation](../README.md#try-the-unreleased-packages) in place of registry install commands.
|
|
10
|
-
|
|
11
9
|
An extension projects your existing Web UI into a SwiftUI View on iOS or Jetpack Compose content on Android. Keep both definitions in your application: no npm package, separate library, or Capacitor plugin is required. The Web element remains the source of truth and the fallback UI.
|
|
12
10
|
|
|
11
|
+
Extensions use the same [projection model](../README.md#how-projection-works) as built-in controls. Define the DOM data and actions to expose, then provide their native presentation.
|
|
12
|
+
|
|
13
13
|
## Before you start
|
|
14
14
|
|
|
15
15
|
Start with an existing Capacitor 8 app and install the plugin if you have not already:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
npm install @rdlabo/capacitor-native-ui
|
|
18
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Choose the native platform you want to support:
|
|
@@ -63,9 +63,18 @@ source.querySelector('button')!.addEventListener('click', () => {
|
|
|
63
63
|
source.querySelector('[data-count-label]')!.textContent = `Count: ${count}`;
|
|
64
64
|
});
|
|
65
65
|
```
|
|
66
|
-
The shell observes DOM changes and sends the new props to the native content. State rendered into DOM attributes or text is observed automatically. For properties or external state read by the reader that do not mutate the DOM, call `shell.markForCheck()` after changing them.
|
|
67
66
|
|
|
68
|
-
The
|
|
67
|
+
The shell observes DOM changes and sends the new props to the native content. State rendered into DOM attributes or text is observed automatically. For properties or external state read by the reader that do not mutate the DOM, call `shell.markForCheck()` after changing them.
|
|
68
|
+
|
|
69
|
+
### Reader contract
|
|
70
|
+
|
|
71
|
+
| Part | Requirement |
|
|
72
|
+
| -------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
73
|
+
| Execution | Synchronous and read-only. |
|
|
74
|
+
| Web fallback | Return `null` when the source should stay on the Web. |
|
|
75
|
+
| `props` | JSON object containing finite numbers, strings, booleans, null, arrays and objects; limited to 64K characters. |
|
|
76
|
+
| Action targets | The source itself or its descendants. Missing, hidden and disabled targets cannot be activated. |
|
|
77
|
+
| Action count | Up to 30 per source. |
|
|
69
78
|
|
|
70
79
|
## 2a. Register a SwiftUI View on iOS
|
|
71
80
|
|
|
@@ -221,14 +230,23 @@ For source-specific fallback reasons, temporarily enable [`debug: true`](configu
|
|
|
221
230
|
|
|
222
231
|
## Content and placement are independent
|
|
223
232
|
|
|
224
|
-
| `placement`
|
|
225
|
-
|
|
|
233
|
+
| `placement` | Behavior |
|
|
234
|
+
| ---------------------- | ------------------------------------------------------------------------------------- |
|
|
226
235
|
| Omitted or `'element'` | Hosts native content in the source element's Web frame on iOS 26+ or Android API 24+. |
|
|
227
|
-
| `'tab-accessory'`
|
|
236
|
+
| `'tab-accessory'` | Attaches the View to a projected tab bar's system SwiftUI tab accessory on iOS 26.1+. |
|
|
237
|
+
|
|
238
|
+
Extensions are independent of `controls` and `ionic.auto`, including with `enableVerticalControlArea()`. The application controls their presentation: return `null` from the reader when a source should stay on the Web, then call `markForCheck()` when that condition changes. Accessories still require their supported native tab host.
|
|
228
239
|
|
|
229
|
-
|
|
240
|
+
### Tab accessory requirements
|
|
230
241
|
|
|
231
|
-
|
|
242
|
+
| Requirement | Supported configuration |
|
|
243
|
+
| ------------------- | ------------------------------------------------------------------------------------------------- |
|
|
244
|
+
| Source location | Inside its owning `ion-tabs`; the shell resolves that element's `ion-tab-bar`. |
|
|
245
|
+
| Native host | Vertical Bars SwiftUI tab host on iOS 26.1+. |
|
|
246
|
+
| Accessory count | A single accessory for the host. |
|
|
247
|
+
| Web fallback layout | Keep an equivalent Web layout, such as a fixed footer; the source retains its space while hidden. |
|
|
248
|
+
|
|
249
|
+
Ordinary UIKit tab bars, missing native tabs, iOS 26.0 or competing accessories keep the source on the Web. Applications do not pass native controller references, and the shell does not approximate a system accessory with a floating overlay.
|
|
232
250
|
|
|
233
251
|
## Read source geometry and presentation state
|
|
234
252
|
|
|
@@ -246,16 +264,16 @@ try NativeUI.register("app.counter") {
|
|
|
246
264
|
|
|
247
265
|
The existing `(props, actions)` closure remains supported. Both forms use the same registration names and duplicate-name checks.
|
|
248
266
|
|
|
249
|
-
| Context property
|
|
250
|
-
|
|
|
251
|
-
| `sourceID`
|
|
252
|
-
| `sourceFrame`
|
|
253
|
-
| `sourceFrameInWebView` | The source rectangle converted to UIKit points in the WebView's local coordinate system; not screen coordinates.
|
|
254
|
-
| `viewportWidth`
|
|
255
|
-
| `pointsPerCSSPixel`
|
|
256
|
-
| `placement`
|
|
257
|
-
| `colorScheme`
|
|
258
|
-
| `layoutDirection`
|
|
267
|
+
| Context property | Meaning |
|
|
268
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
269
|
+
| `sourceID` | Opaque source identity for its current lifetime; not the HTML `id`. |
|
|
270
|
+
| `sourceFrame` | DOM `getBoundingClientRect()` in CSS pixels relative to the Web viewport, including `x`, `y`, `width`, and `height`. |
|
|
271
|
+
| `sourceFrameInWebView` | The source rectangle converted to UIKit points in the WebView's local coordinate system; not screen coordinates. |
|
|
272
|
+
| `viewportWidth` | CSS viewport width used for that snapshot's coordinate conversion. |
|
|
273
|
+
| `pointsPerCSSPixel` | UIKit points per CSS pixel; not device pixel density. |
|
|
274
|
+
| `placement` | `.element` or `.tabAccessory`. |
|
|
275
|
+
| `colorScheme` | `.light` or `.dark`, also applied to the SwiftUI environment. |
|
|
276
|
+
| `layoutDirection` | `.leftToRight` or `.rightToLeft`, also applied to the SwiftUI environment. |
|
|
259
277
|
|
|
260
278
|
The closure receives a fresh context when the shell applies an updated snapshot, including source movement, resizing, and appearance changes. Use the current context rather than caching its geometry in `@State`. Updates cross the Web/native bridge; they are not a synchronous DOM measurement from Swift.
|
|
261
279
|
|
|
@@ -272,16 +290,16 @@ Do not apply `sourceFrame.x` or `y` as another SwiftUI offset: the shell already
|
|
|
272
290
|
|
|
273
291
|
## Use the shared projection capabilities
|
|
274
292
|
|
|
275
|
-
| Capability
|
|
276
|
-
|
|
|
277
|
-
| Position and size
|
|
278
|
-
| Dark mode and RTL
|
|
279
|
-
| Reduce Motion and accessibility
|
|
280
|
-
| DOM-backed application state
|
|
281
|
-
| Enabled/visible action targets
|
|
282
|
-
| Invoke the original Web action
|
|
283
|
-
| Temporary Web fallback and teardown | Managed automatically for unsupported content, overlays, navigation suspension, and source removal.
|
|
284
|
-
| Application-controlled suspension
|
|
293
|
+
| Capability | How an extension uses it |
|
|
294
|
+
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
295
|
+
| Position and size | Automatic host placement plus `NativeUIContext`; actual local bounds through `GeometryReader`. |
|
|
296
|
+
| Dark mode and RTL | `context` or SwiftUI `@Environment(\.colorScheme)` and `@Environment(\.layoutDirection)`. |
|
|
297
|
+
| Reduce Motion and accessibility | SwiftUI environment values such as `@Environment(\.accessibilityReduceMotion)` and native accessibility modifiers. Give custom controls accessible names. |
|
|
298
|
+
| DOM-backed application state | Return JSON `props` from `read(element)`; DOM changes trigger synchronization. For changes without a DOM mutation, call `shell.markForCheck()`. |
|
|
299
|
+
| Enabled/visible action targets | `actions.availableNames` or `actions.isAvailable("increment")`; unavailable DOM targets are omitted. |
|
|
300
|
+
| Invoke the original Web action | `try await actions.activate("increment")`; completion and failure follow the contract below. |
|
|
301
|
+
| Temporary Web fallback and teardown | Managed automatically for unsupported content, overlays, navigation suspension, and source removal. |
|
|
302
|
+
| Application-controlled suspension | Use the shell handle's `suspend()`, the returned token's `resume()`, and `destroy()` from JavaScript. |
|
|
285
303
|
|
|
286
304
|
For example, disable a native button when its original action is unavailable:
|
|
287
305
|
|
|
@@ -358,8 +376,19 @@ The shell owns discovery, geometry, state synchronization, native controller con
|
|
|
358
376
|
|
|
359
377
|
Element placement requires the source to fit fully inside the viewport and its ancestors' overflow clipping bounds, including Ionic's shadow scroll containers. Partially clipped sources stay on the Web and become eligible again when scrolled fully into view. Tab accessories use the system host's placement instead.
|
|
360
378
|
|
|
361
|
-
|
|
379
|
+
### Action completion
|
|
380
|
+
|
|
381
|
+
| Event | Result of `try await actions.activate(name)` |
|
|
382
|
+
| ------------------------------------------------------------------ | -------------------------------------------- |
|
|
383
|
+
| Original Web element receives its click | Completes. |
|
|
384
|
+
| Handler starts a network request, navigation or modal presentation | Does not wait for that application work. |
|
|
385
|
+
| Action is disabled, removed or stale | Rejects. |
|
|
386
|
+
| Teardown, native task cancellation or bridge timeout | Settles pending calls. |
|
|
387
|
+
|
|
388
|
+
The bridge acknowledgement is a Capacitor Promise method.
|
|
362
389
|
|
|
363
390
|
The [demo reader](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/src/native-ui/counter.ts) and [demo SwiftUI View](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/ios/App/App/NativeUICounter.swift) show both placements using app-local files. Open the Native UI demo page to compare native projection with its Web fallback.
|
|
364
391
|
|
|
365
|
-
|
|
392
|
+
## Example: mini-player
|
|
393
|
+
|
|
394
|
+
The demo mini-player shows the same pattern with track metadata and playback actions: a [DOM reader and Web fallback](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/src/native-ui/mini-player.ts) paired with an [app-local SwiftUI View](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/ios/App/App/NativeMiniPlayer.swift). The Web app owns playback state and modal presentation; native `open` and `toggle` actions activate its original buttons. This is a UI example, not an audio engine. Adapt the files after completing the extension setup above.
|