@symbiote-native/angular 0.0.0-canary-20260724081123
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/LICENSE +21 -0
- package/README.md +157 -0
- package/babel-linker.cjs +7 -0
- package/babel-register-composed.cjs +127 -0
- package/bin/symbiote-angular-dev.cjs +93 -0
- package/build/angular/anchor-host-registry.d.ts +2 -0
- package/build/angular/anchor-host-registry.js +84 -0
- package/build/angular/anchor-host-registry.js.map +1 -0
- package/build/angular/bootstrap.d.ts +7 -0
- package/build/angular/bootstrap.js +15 -0
- package/build/angular/bootstrap.js.map +1 -0
- package/build/angular/components/activity-indicator/index.android.d.ts +12 -0
- package/build/angular/components/activity-indicator/index.android.js +21 -0
- package/build/angular/components/activity-indicator/index.android.js.map +1 -0
- package/build/angular/components/activity-indicator/index.d.ts +1 -0
- package/build/angular/components/activity-indicator/index.ios.d.ts +8 -0
- package/build/angular/components/activity-indicator/index.ios.js +21 -0
- package/build/angular/components/activity-indicator/index.ios.js.map +1 -0
- package/build/angular/components/activity-indicator/index.js +4 -0
- package/build/angular/components/activity-indicator/index.js.map +1 -0
- package/build/angular/components/activity-indicator/shared.d.ts +67 -0
- package/build/angular/components/activity-indicator/shared.js +260 -0
- package/build/angular/components/activity-indicator/shared.js.map +1 -0
- package/build/angular/components/button.d.ts +63 -0
- package/build/angular/components/button.js +332 -0
- package/build/angular/components/button.js.map +1 -0
- package/build/angular/components/flat-list/index.d.ts +122 -0
- package/build/angular/components/flat-list/index.js +688 -0
- package/build/angular/components/flat-list/index.js.map +1 -0
- package/build/angular/components/image/index.android.d.ts +10 -0
- package/build/angular/components/image/index.android.js +59 -0
- package/build/angular/components/image/index.android.js.map +1 -0
- package/build/angular/components/image/index.d.ts +1 -0
- package/build/angular/components/image/index.ios.d.ts +10 -0
- package/build/angular/components/image/index.ios.js +59 -0
- package/build/angular/components/image/index.ios.js.map +1 -0
- package/build/angular/components/image/index.js +3 -0
- package/build/angular/components/image/index.js.map +1 -0
- package/build/angular/components/image/shared.d.ts +101 -0
- package/build/angular/components/image/shared.js +406 -0
- package/build/angular/components/image/shared.js.map +1 -0
- package/build/angular/components/image-background.d.ts +81 -0
- package/build/angular/components/image-background.js +418 -0
- package/build/angular/components/image-background.js.map +1 -0
- package/build/angular/components/input-accessory-view/index.d.ts +60 -0
- package/build/angular/components/input-accessory-view/index.js +251 -0
- package/build/angular/components/input-accessory-view/index.js.map +1 -0
- package/build/angular/components/keyboard-avoiding-view/index.d.ts +82 -0
- package/build/angular/components/keyboard-avoiding-view/index.js +358 -0
- package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -0
- package/build/angular/components/modal/index.d.ts +92 -0
- package/build/angular/components/modal/index.js +360 -0
- package/build/angular/components/modal/index.js.map +1 -0
- package/build/angular/components/pressable/index.d.ts +123 -0
- package/build/angular/components/pressable/index.js +420 -0
- package/build/angular/components/pressable/index.js.map +1 -0
- package/build/angular/components/refresh-control/index.d.ts +86 -0
- package/build/angular/components/refresh-control/index.js +342 -0
- package/build/angular/components/refresh-control/index.js.map +1 -0
- package/build/angular/components/safe-area-view/index.d.ts +57 -0
- package/build/angular/components/safe-area-view/index.js +248 -0
- package/build/angular/components/safe-area-view/index.js.map +1 -0
- package/build/angular/components/scroll-view/index.android.d.ts +21 -0
- package/build/angular/components/scroll-view/index.android.js +235 -0
- package/build/angular/components/scroll-view/index.android.js.map +1 -0
- package/build/angular/components/scroll-view/index.d.ts +3 -0
- package/build/angular/components/scroll-view/index.ios.d.ts +9 -0
- package/build/angular/components/scroll-view/index.ios.js +86 -0
- package/build/angular/components/scroll-view/index.ios.js.map +1 -0
- package/build/angular/components/scroll-view/index.js +6 -0
- package/build/angular/components/scroll-view/index.js.map +1 -0
- package/build/angular/components/scroll-view/projection.d.ts +32 -0
- package/build/angular/components/scroll-view/projection.js +334 -0
- package/build/angular/components/scroll-view/projection.js.map +1 -0
- package/build/angular/components/scroll-view/shared.d.ts +230 -0
- package/build/angular/components/scroll-view/shared.js +682 -0
- package/build/angular/components/scroll-view/shared.js.map +1 -0
- package/build/angular/components/scroll-view/sticky-header.d.ts +40 -0
- package/build/angular/components/scroll-view/sticky-header.js +225 -0
- package/build/angular/components/scroll-view/sticky-header.js.map +1 -0
- package/build/angular/components/section-list/index.d.ts +116 -0
- package/build/angular/components/section-list/index.js +641 -0
- package/build/angular/components/section-list/index.js.map +1 -0
- package/build/angular/components/switch/index.android.d.ts +20 -0
- package/build/angular/components/switch/index.android.js +70 -0
- package/build/angular/components/switch/index.android.js.map +1 -0
- package/build/angular/components/switch/index.d.ts +1 -0
- package/build/angular/components/switch/index.ios.d.ts +19 -0
- package/build/angular/components/switch/index.ios.js +69 -0
- package/build/angular/components/switch/index.ios.js.map +1 -0
- package/build/angular/components/switch/index.js +4 -0
- package/build/angular/components/switch/index.js.map +1 -0
- package/build/angular/components/switch/shared.d.ts +40 -0
- package/build/angular/components/switch/shared.js +127 -0
- package/build/angular/components/switch/shared.js.map +1 -0
- package/build/angular/components/text-input.d.ts +153 -0
- package/build/angular/components/text-input.js +599 -0
- package/build/angular/components/text-input.js.map +1 -0
- package/build/angular/components/touchable/index.d.ts +245 -0
- package/build/angular/components/touchable/index.js +1186 -0
- package/build/angular/components/touchable/index.js.map +1 -0
- package/build/angular/components/touchable-native-feedback/index.d.ts +83 -0
- package/build/angular/components/touchable-native-feedback/index.js +371 -0
- package/build/angular/components/touchable-native-feedback/index.js.map +1 -0
- package/build/angular/components/virtualized-list/directives.d.ts +54 -0
- package/build/angular/components/virtualized-list/directives.js +153 -0
- package/build/angular/components/virtualized-list/directives.js.map +1 -0
- package/build/angular/components/virtualized-list/index.d.ts +253 -0
- package/build/angular/components/virtualized-list/index.js +1031 -0
- package/build/angular/components/virtualized-list/index.js.map +1 -0
- package/build/angular/components/virtualized-section-list/directives.d.ts +37 -0
- package/build/angular/components/virtualized-section-list/directives.js +76 -0
- package/build/angular/components/virtualized-section-list/directives.js.map +1 -0
- package/build/angular/components/virtualized-section-list/index.d.ts +178 -0
- package/build/angular/components/virtualized-section-list/index.js +720 -0
- package/build/angular/components/virtualized-section-list/index.js.map +1 -0
- package/build/angular/components.d.ts +39 -0
- package/build/angular/components.js +38 -0
- package/build/angular/components.js.map +1 -0
- package/build/angular/create-portal/index.d.ts +22 -0
- package/build/angular/create-portal/index.js +74 -0
- package/build/angular/create-portal/index.js.map +1 -0
- package/build/angular/create-tunnel/index.d.ts +34 -0
- package/build/angular/create-tunnel/index.js +126 -0
- package/build/angular/create-tunnel/index.js.map +1 -0
- package/build/angular/descriptor-to-angular/index.d.ts +22 -0
- package/build/angular/descriptor-to-angular/index.js +142 -0
- package/build/angular/descriptor-to-angular/index.js.map +1 -0
- package/build/angular/host-instance/index.d.ts +2 -0
- package/build/angular/host-instance/index.js +37 -0
- package/build/angular/host-instance/index.js.map +1 -0
- package/build/angular/index.d.ts +22 -0
- package/build/angular/index.js +46 -0
- package/build/angular/index.js.map +1 -0
- package/build/angular/modules/animated/animated-leaf-binder/index.d.ts +14 -0
- package/build/angular/modules/animated/animated-leaf-binder/index.js +91 -0
- package/build/angular/modules/animated/animated-leaf-binder/index.js.map +1 -0
- package/build/angular/modules/animated/animated-leaf-binder.d.ts +14 -0
- package/build/angular/modules/animated/animated-leaf-binder.js +91 -0
- package/build/angular/modules/animated/animated-leaf-binder.js.map +1 -0
- package/build/angular/modules/animated/create-animated-component.d.ts +59 -0
- package/build/angular/modules/animated/create-animated-component.js +364 -0
- package/build/angular/modules/animated/create-animated-component.js.map +1 -0
- package/build/angular/modules/animated/index.d.ts +51 -0
- package/build/angular/modules/animated/index.js +59 -0
- package/build/angular/modules/animated/index.js.map +1 -0
- package/build/angular/modules/app-registry/index.d.ts +7 -0
- package/build/angular/modules/app-registry/index.js +23 -0
- package/build/angular/modules/app-registry/index.js.map +1 -0
- package/build/angular/modules/status-bar/index.d.ts +20 -0
- package/build/angular/modules/status-bar/index.js +59 -0
- package/build/angular/modules/status-bar/index.js.map +1 -0
- package/build/angular/primitives/index.d.ts +63 -0
- package/build/angular/primitives/index.js +189 -0
- package/build/angular/primitives/index.js.map +1 -0
- package/build/angular/primitives/shared.d.ts +88 -0
- package/build/angular/primitives/shared.js +171 -0
- package/build/angular/primitives/shared.js.map +1 -0
- package/build/angular/render/index.d.ts +11 -0
- package/build/angular/render/index.js +171 -0
- package/build/angular/render/index.js.map +1 -0
- package/build/angular/renderer/index.d.ts +37 -0
- package/build/angular/renderer/index.js +301 -0
- package/build/angular/renderer/index.js.map +1 -0
- package/build/angular/services/color-scheme.service.d.ts +16 -0
- package/build/angular/services/color-scheme.service.js +31 -0
- package/build/angular/services/color-scheme.service.js.map +1 -0
- package/build/angular/services/index.d.ts +2 -0
- package/build/angular/services/index.js +3 -0
- package/build/angular/services/index.js.map +1 -0
- package/build/angular/services/window-dimensions.service.d.ts +16 -0
- package/build/angular/services/window-dimensions.service.js +42 -0
- package/build/angular/services/window-dimensions.service.js.map +1 -0
- package/metro-config.cjs +48 -0
- package/metro-css-parser.cjs +13 -0
- package/package.json +80 -0
- package/src/__tests__/responder-change-detection.test.ts +102 -0
- package/src/__tests__/responder-nested-cd.test.ts +113 -0
- package/src/anchor-host-registry.ts +88 -0
- package/src/angular-gaps.test.ts +142 -0
- package/src/angular-imports.test.ts +100 -0
- package/src/bootstrap.ts +26 -0
- package/src/components/activity-indicator/activity-indicator-class-style.test.ts +44 -0
- package/src/components/activity-indicator/activity-indicator.test.ts +131 -0
- package/src/components/activity-indicator/index.android.ts +16 -0
- package/src/components/activity-indicator/index.ios.ts +17 -0
- package/src/components/activity-indicator/index.ts +4 -0
- package/src/components/activity-indicator/shared.ts +206 -0
- package/src/components/button.ts +193 -0
- package/src/components/flat-list/column-wrapper-style-class.test.ts +116 -0
- package/src/components/flat-list/flat-list-array-style.test.ts +131 -0
- package/src/components/flat-list/flat-list-class-style.test.ts +74 -0
- package/src/components/flat-list/flat-list-scroll-containment.test.ts +107 -0
- package/src/components/flat-list/flat-list.test.ts +99 -0
- package/src/components/flat-list/index.ts +574 -0
- package/src/components/image/image-class-style.test.ts +46 -0
- package/src/components/image/index.android.ts +48 -0
- package/src/components/image/index.ios.ts +48 -0
- package/src/components/image/index.ts +3 -0
- package/src/components/image/shared.ts +479 -0
- package/src/components/image-background-class-style.test.ts +48 -0
- package/src/components/image-background-style-class.test.ts +79 -0
- package/src/components/image-background.ts +270 -0
- package/src/components/input-accessory-view/index.ts +185 -0
- package/src/components/input-accessory-view/input-accessory-view.test.ts +43 -0
- package/src/components/keyboard-avoiding-view/index.ts +303 -0
- package/src/components/keyboard-avoiding-view/keyboard-avoiding-view.test.ts +54 -0
- package/src/components/modal/index.ts +299 -0
- package/src/components/modal/modal.test.ts +43 -0
- package/src/components/pressable/index.ts +373 -0
- package/src/components/pressable/pressable.test.ts +85 -0
- package/src/components/refresh-control/index.ts +284 -0
- package/src/components/refresh-control/refresh-control.test.ts +41 -0
- package/src/components/safe-area-view/index.ts +177 -0
- package/src/components/safe-area-view/safe-area-view.test.ts +43 -0
- package/src/components/scroll-view/android-scroll-view-axis-projection.test.ts +123 -0
- package/src/components/scroll-view/content-container-style-class.test.ts +75 -0
- package/src/components/scroll-view/index.android.ts +190 -0
- package/src/components/scroll-view/index.ios.ts +79 -0
- package/src/components/scroll-view/index.ts +7 -0
- package/src/components/scroll-view/projection.ts +414 -0
- package/src/components/scroll-view/scroll-view-class-style.test.ts +134 -0
- package/src/components/scroll-view/scroll-view-projection.test.ts +194 -0
- package/src/components/scroll-view/shared.ts +844 -0
- package/src/components/scroll-view/sticky-header.ts +255 -0
- package/src/components/section-list/index.ts +445 -0
- package/src/components/switch/android-switch-class.test.ts +42 -0
- package/src/components/switch/index.android.ts +61 -0
- package/src/components/switch/index.ios.ts +60 -0
- package/src/components/switch/index.ts +4 -0
- package/src/components/switch/shared.ts +197 -0
- package/src/components/switch/switch.test.ts +92 -0
- package/src/components/text-input-class-style.test.ts +54 -0
- package/src/components/text-input.ts +531 -0
- package/src/components/touchable/index.ts +629 -0
- package/src/components/touchable/touchable.test.ts +102 -0
- package/src/components/touchable-native-feedback/index.ts +254 -0
- package/src/components/touchable-native-feedback/touchable-native-feedback.test.ts +49 -0
- package/src/components/virtualized-list/directives.ts +168 -0
- package/src/components/virtualized-list/index.ts +992 -0
- package/src/components/virtualized-list/virtualized-list-class-style.test.ts +76 -0
- package/src/components/virtualized-section-list/directives.ts +90 -0
- package/src/components/virtualized-section-list/index.ts +601 -0
- package/src/components/virtualized-section-list/virtualized-section-list-class-style.test.ts +60 -0
- package/src/components.ts +149 -0
- package/src/create-portal/create-portal.test.ts +90 -0
- package/src/create-portal/index.ts +74 -0
- package/src/create-tunnel/create-tunnel.test.ts +120 -0
- package/src/create-tunnel/index.ts +136 -0
- package/src/descriptor-to-angular/descriptor-outlet.test.ts +94 -0
- package/src/descriptor-to-angular/index.ts +190 -0
- package/src/host-instance/host-instance.test.ts +49 -0
- package/src/host-instance/index.ts +36 -0
- package/src/index.ts +261 -0
- package/src/modules/animated/animated-leaf-binder/animated-leaf-binder.test.ts +116 -0
- package/src/modules/animated/animated-leaf-binder/index.ts +101 -0
- package/src/modules/animated/animated-leaf-binder.test.ts +116 -0
- package/src/modules/animated/animated-leaf-binder.ts +101 -0
- package/src/modules/animated/animated-scroll-view.test.ts +102 -0
- package/src/modules/animated/create-animated-component.ts +365 -0
- package/src/modules/animated/index.ts +105 -0
- package/src/modules/app-registry/app-registry.test.ts +106 -0
- package/src/modules/app-registry/index.ts +60 -0
- package/src/modules/status-bar/index.ts +57 -0
- package/src/modules/status-bar/status-bar.test.ts +50 -0
- package/src/primitives/index.ts +119 -0
- package/src/primitives/shared.ts +190 -0
- package/src/render/index.ts +235 -0
- package/src/render/render.test.ts +147 -0
- package/src/renderer/index.ts +347 -0
- package/src/renderer/renderer.test.ts +203 -0
- package/src/services/color-scheme.service.ts +27 -0
- package/src/services/index.ts +2 -0
- package/src/services/services.test.ts +163 -0
- package/src/services/window-dimensions.service.ts +41 -0
- package/tsconfig.angular.base.json +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 A. Prokopenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# @symbiote-native/angular
|
|
2
|
+
|
|
3
|
+
The **Angular adapter** for [SymbioteNative](../../README.md) — render real native iOS/Android views
|
|
4
|
+
from Angular, on the *same* untouched core as React and Vue, with React Native's own renderer
|
|
5
|
+
never in the path. It is a `Renderer2`/`RendererFactory2` whose calls map onto the engine's
|
|
6
|
+
four-call mutation API; `@symbiote-native/engine` does the clone-on-write commit into Fabric.
|
|
7
|
+
|
|
8
|
+
Angular is the **second proof the core is genuinely framework-agnostic**: a third
|
|
9
|
+
framework, with its own change-detection model and AOT compilation pipeline, driving the
|
|
10
|
+
already-validated engine with zero changes to it.
|
|
11
|
+
|
|
12
|
+
<div align="center">
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
> New to SymbioteNative? The [root README](../../README.md) has the architecture.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @symbiote-native/angular react-native @angular/core
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`react-native` and `@angular/core` (**>=20**, for stable zoneless change detection) stay your app's
|
|
29
|
+
own top-level dependencies. There's no `create-symbiote` scaffolder yet, so the AOT pipeline
|
|
30
|
+
(`ngc --watch` alongside Metro — see [Run it](#run-it)) and the Metro config come from
|
|
31
|
+
[`examples/angular`](../../examples/angular) rather than a generator.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Use it
|
|
36
|
+
|
|
37
|
+
The native entry reaches the *same* `registerRunnable` seam as React and Vue — only the adapter
|
|
38
|
+
changes. It hands the surface's `rootTag` to `mount` from `@symbiote-native/angular`, which drives the
|
|
39
|
+
engine through Angular's `Renderer2`:
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
// index.js
|
|
43
|
+
import { AppRegistry as RNAppRegistry } from 'react-native';
|
|
44
|
+
import { mount } from '@symbiote-native/angular';
|
|
45
|
+
import { AppComponent } from './App';
|
|
46
|
+
import { name as appName } from './app.json';
|
|
47
|
+
|
|
48
|
+
// registerRunnable (not registerComponent): RN stores a raw mount callback and never renders
|
|
49
|
+
// it with its own renderer. We mount the Angular app onto the surface's rootTag.
|
|
50
|
+
RNAppRegistry.registerRunnable(appName, ({ rootTag }) => {
|
|
51
|
+
mount(rootTag, AppComponent);
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The app is ordinary standalone Angular — it just imports primitives from `@symbiote-native/angular`
|
|
56
|
+
instead of `react-native`. A tap→increment counter:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { Component, signal } from '@angular/core';
|
|
60
|
+
import { View, Text, Pressable } from '@symbiote-native/angular';
|
|
61
|
+
|
|
62
|
+
@Component({
|
|
63
|
+
selector: 'app-root',
|
|
64
|
+
standalone: true,
|
|
65
|
+
imports: [View, Text, Pressable],
|
|
66
|
+
template: `
|
|
67
|
+
<View [style]="{ padding: 24 }">
|
|
68
|
+
<Text>Taps: {{ count() }}</Text>
|
|
69
|
+
<Pressable (press)="count.set(count() + 1)">
|
|
70
|
+
<Text>Tap me</Text>
|
|
71
|
+
</Pressable>
|
|
72
|
+
</View>
|
|
73
|
+
`,
|
|
74
|
+
})
|
|
75
|
+
export class AppComponent {
|
|
76
|
+
count = signal(0);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The full canary is [`examples/angular`](../../examples/angular) — a stock RN 0.86 app whose
|
|
81
|
+
[`App.ts`](../../examples/angular/App.ts) exercises the same surface as the React and Vue
|
|
82
|
+
reference canaries, standalone components, zoneless change detection.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Parity — and the one gap
|
|
87
|
+
|
|
88
|
+
Angular reaches the same 21+ primitives, runtime modules, `Animated` on both drivers, gestures,
|
|
89
|
+
accessibility, and the `VirtualizedList` family as React and Vue. That parity is **structural, not
|
|
90
|
+
hand-copied**: the component logic (state machines + render functions) is written **once** in
|
|
91
|
+
`@symbiote-native/components`, and Angular supplies only its lifecycle (`Renderer2` + zoneless change
|
|
92
|
+
detection + the descriptor→`createElement` bridge).
|
|
93
|
+
|
|
94
|
+
One deliberate gap, tracked, not blocking the canary — **third-party React component packages**
|
|
95
|
+
(`@react-native-community/slider`) run only under the React adapter: their body calls React hooks
|
|
96
|
+
off the React dispatcher, which is null under Angular. `@symbiote-native/slider` (this repo's own
|
|
97
|
+
wrapper) *does* ship a real Angular build, reachable through the same `createNode`-by-ViewConfig
|
|
98
|
+
path Angular uses for its own primitives — that wrapper is what makes a third-party native view
|
|
99
|
+
usable from a non-React adapter at all.
|
|
100
|
+
|
|
101
|
+
Angular is on the docs site's live framework switcher alongside React and Vue — otherwise it's at
|
|
102
|
+
full canary parity.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## An Angular-specific gotcha — AOT compiles separately from Metro
|
|
107
|
+
|
|
108
|
+
Angular templates need `ngc` (Angular's own AOT compiler), which Metro cannot run per-file the way
|
|
109
|
+
it transforms a Vue SFC or JSX — `ngc` needs whole-program `compilationMode: 'partial'` first, then
|
|
110
|
+
`@angular/compiler-cli/linker/babel` drops the linked output into Metro per-file. In practice this
|
|
111
|
+
means every `ios`/`android`/`e2e:build:*` script runs `pnpm ng:build` first, and local development
|
|
112
|
+
needs `ngc --watch` running alongside Metro — `scripts/dev-with-watch.sh` in
|
|
113
|
+
[`examples/angular`](../../examples/angular) does exactly that (`ngc --watch` in the background,
|
|
114
|
+
Metro's `react-native start` in the foreground, since Metro reads raw keypresses off stdin and
|
|
115
|
+
can't sit behind a process manager that owns stdin itself).
|
|
116
|
+
|
|
117
|
+
Angular also requires **zoneless change detection** (`provideZonelessChangeDetection`,
|
|
118
|
+
`@angular/core >=20`) — zone.js fights Hermes, and versions before 20 don't offer a stable
|
|
119
|
+
zoneless API. This is the version floor for the whole adapter, not a suggestion.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Run it
|
|
124
|
+
|
|
125
|
+
[`examples/angular`](../../examples/angular) is a stock React Native 0.86 app. Requires Node ≥
|
|
126
|
+
22.13 and the [RN environment setup](https://reactnative.dev/docs/set-up-your-environment) (Xcode,
|
|
127
|
+
CocoaPods):
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd examples/angular
|
|
131
|
+
pnpm install # workspace root already covers this if you ran it there
|
|
132
|
+
bundle install # first time only — installs CocoaPods itself
|
|
133
|
+
bundle exec pod install # fetch native pods
|
|
134
|
+
|
|
135
|
+
# terminal 1 — ngc --watch (background) + Metro (foreground). DEBUG=1 turns on diagnostic logs.
|
|
136
|
+
DEBUG=1 pnpm dev
|
|
137
|
+
|
|
138
|
+
# terminal 2 — build + launch (each runs ng:build first)
|
|
139
|
+
pnpm ios # iOS simulator
|
|
140
|
+
pnpm android # Android emulator
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Test it
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
pnpm test # vitest, from the workspace root — headless, fake Fabric slot
|
|
149
|
+
|
|
150
|
+
cd examples/angular
|
|
151
|
+
pnpm e2e:build:ios # ng:build, then build the app for Detox
|
|
152
|
+
pnpm e2e:test:ios # run the canary journeys on the iOS simulator
|
|
153
|
+
# …or the android equivalents: e2e:build:android / e2e:test:android
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Why these come for free — a SymbioteNative app is a stock RN app underneath, so RN's whole testing
|
|
157
|
+
ecosystem applies unchanged. See [Testing](../../README.md#testing).
|
package/babel-linker.cjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Normalizes @angular/compiler-cli/linker/babel's export shape — depending on how a
|
|
2
|
+
// consumer's Metro/Babel setup loads it, the plugin lands as either the plugin function itself
|
|
3
|
+
// or a `{ default: plugin }` wrapper — so a consumer's babel.config.js just requires this
|
|
4
|
+
// instead of re-deriving the `.default ?? angularLinker` fallback itself.
|
|
5
|
+
const angularLinkerModule = require('@angular/compiler-cli/linker/babel');
|
|
6
|
+
|
|
7
|
+
module.exports = angularLinkerModule.default ?? angularLinkerModule;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Auto-registers ANCHOR_HOST_COMPONENTS from compiled @Component metadata, replacing
|
|
2
|
+
// hand-written registerComposedComponent(...) calls (see the angular-adapter skill §11).
|
|
3
|
+
// Runs in the SAME Babel pass as babel-linker.cjs, BEFORE it — Stage A (ngc --compilationMode
|
|
4
|
+
// partial) emits ɵɵngDeclareComponent({..., selector}) calls; the linker only turns those into
|
|
5
|
+
// full Ivy afterwards, so this plugin must see the simpler pre-link shape (see
|
|
6
|
+
// angular-adapter-build skill §1).
|
|
7
|
+
//
|
|
8
|
+
// Primitive selectors are hardcoded here (not required from the .ts source — this is a plain
|
|
9
|
+
// .cjs Babel plugin Metro loads via a raw require(), no transpile step available) — source of
|
|
10
|
+
// truth: core/components/src/component-names/index.ios.ts's ISymbioteIntrinsic union. Kept in
|
|
11
|
+
// sync by the drift-protection test in babel-register-composed.test.ts.
|
|
12
|
+
const PRIMITIVE_SELECTORS = new Set([
|
|
13
|
+
'symbiote-view',
|
|
14
|
+
'symbiote-text',
|
|
15
|
+
'symbiote-image',
|
|
16
|
+
'symbiote-scroll-view',
|
|
17
|
+
'symbiote-scroll-content',
|
|
18
|
+
'symbiote-horizontal-scroll-view',
|
|
19
|
+
'symbiote-horizontal-scroll-content',
|
|
20
|
+
'symbiote-text-input',
|
|
21
|
+
'symbiote-text-input-multiline',
|
|
22
|
+
'symbiote-switch',
|
|
23
|
+
'symbiote-activity-indicator',
|
|
24
|
+
'symbiote-safe-area-view',
|
|
25
|
+
'symbiote-modal',
|
|
26
|
+
'symbiote-refresh-control',
|
|
27
|
+
'symbiote-input-accessory-view',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
// Inject from the package barrel — the ONE resolution route every consumer already uses, so the
|
|
31
|
+
// leaf's registry Set stays a single module instance. `registerComposedComponent` is re-exported
|
|
32
|
+
// from the barrel straight off the dependency-free leaf `anchor-host-registry.ts`, so importing it
|
|
33
|
+
// here does NOT drag in the cyclic renderer graph, yet resolves to the same leaf Set that
|
|
34
|
+
// `createElement` reads. (An earlier attempt injected a dedicated `.../anchor-host-registry`
|
|
35
|
+
// subpath instead; under pnpm symlinks that gave the leaf a SECOND resolved path — a second Set —
|
|
36
|
+
// so navigation-package registrations and createElement's lookup desynced. See the leaf header +
|
|
37
|
+
// angular-adapter §11c.)
|
|
38
|
+
const IMPORT_SOURCE = '@symbiote-native/angular';
|
|
39
|
+
const HELPER_NAME = 'registerComposedComponent';
|
|
40
|
+
|
|
41
|
+
function isNgDeclareComponentCall(node) {
|
|
42
|
+
return (
|
|
43
|
+
node.type === 'CallExpression' &&
|
|
44
|
+
node.callee.type === 'MemberExpression' &&
|
|
45
|
+
!node.callee.computed &&
|
|
46
|
+
node.callee.property.type === 'Identifier' &&
|
|
47
|
+
node.callee.property.name === 'ɵɵngDeclareComponent'
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function selectorPropertyOf(objectExpression) {
|
|
52
|
+
return objectExpression.properties.find(
|
|
53
|
+
prop =>
|
|
54
|
+
prop.type === 'ObjectProperty' &&
|
|
55
|
+
!prop.computed &&
|
|
56
|
+
((prop.key.type === 'Identifier' && prop.key.name === 'selector') ||
|
|
57
|
+
(prop.key.type === 'StringLiteral' && prop.key.value === 'selector')),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function composedSelectorsFromCall(node) {
|
|
62
|
+
const [arg] = node.arguments;
|
|
63
|
+
if (!arg || arg.type !== 'ObjectExpression') return [];
|
|
64
|
+
const selectorProp = selectorPropertyOf(arg);
|
|
65
|
+
if (!selectorProp || selectorProp.value.type !== 'StringLiteral') return [];
|
|
66
|
+
return selectorProp.value.value
|
|
67
|
+
.split(',')
|
|
68
|
+
.map(token => token.trim())
|
|
69
|
+
.filter(token => token.length > 0 && !PRIMITIVE_SELECTORS.has(token));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function hasComposedImport(programNode) {
|
|
73
|
+
return programNode.body.some(
|
|
74
|
+
node =>
|
|
75
|
+
node.type === 'ImportDeclaration' &&
|
|
76
|
+
node.source.value === IMPORT_SOURCE &&
|
|
77
|
+
node.specifiers.some(
|
|
78
|
+
spec =>
|
|
79
|
+
spec.type === 'ImportSpecifier' &&
|
|
80
|
+
spec.imported.type === 'Identifier' &&
|
|
81
|
+
spec.imported.name === HELPER_NAME,
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Exposed as a property on the plugin function (not a separate export) so Babel still loads
|
|
87
|
+
// this file as a plain plugin factory; babel-register-composed.test.ts's drift-protection test
|
|
88
|
+
// reads it to compare against core/components/src/component-names/index.{ios,android}.ts.
|
|
89
|
+
module.exports = function registerComposedPlugin({ types: t }) {
|
|
90
|
+
return {
|
|
91
|
+
name: 'symbiote-register-composed',
|
|
92
|
+
visitor: {
|
|
93
|
+
Program(programPath) {
|
|
94
|
+
const selectors = new Set();
|
|
95
|
+
programPath.traverse({
|
|
96
|
+
CallExpression(path) {
|
|
97
|
+
if (isNgDeclareComponentCall(path.node)) {
|
|
98
|
+
for (const selector of composedSelectorsFromCall(path.node)) selectors.add(selector);
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
if (selectors.size === 0) return;
|
|
103
|
+
|
|
104
|
+
const statements = [...selectors].map(selector =>
|
|
105
|
+
t.expressionStatement(
|
|
106
|
+
t.callExpression(t.identifier(HELPER_NAME), [t.stringLiteral(selector)]),
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (!hasComposedImport(programPath.node)) {
|
|
111
|
+
statements.unshift(
|
|
112
|
+
t.importDeclaration(
|
|
113
|
+
[t.importSpecifier(t.identifier(HELPER_NAME), t.identifier(HELPER_NAME))],
|
|
114
|
+
t.stringLiteral(IMPORT_SOURCE),
|
|
115
|
+
),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Import hoisting makes textual position irrelevant to `registerComposedComponent`'s
|
|
120
|
+
// availability, so unshifting the whole batch to the top keeps this single-pass.
|
|
121
|
+
programPath.unshiftContainer('body', statements);
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
module.exports.PRIMITIVE_SELECTORS = PRIMITIVE_SELECTORS;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Cross-platform replacement for the old per-app dev-with-watch.sh: Angular needs a pre-Metro
|
|
3
|
+
// AOT compile (ngc), kept in sync via `ngc --watch` while developing. Metro itself must stay
|
|
4
|
+
// the FOREGROUND process — it reads raw keypresses
|
|
5
|
+
// (r/j/d/...) straight off stdin, and any wrapper that pipes stdin through itself
|
|
6
|
+
// (concurrently, npm-run-all, ...) breaks that raw-mode read. So ngc runs as a plain background
|
|
7
|
+
// child process, never a stdin-owning process manager. `shell: true` resolves `ngc`/
|
|
8
|
+
// `react-native` off PATH exactly like the bash script did — npm/pnpm/yarn already prepend
|
|
9
|
+
// every `node_modules/.bin` up the tree to PATH for any script invocation, this one included.
|
|
10
|
+
const { spawn, spawnSync } = require('node:child_process');
|
|
11
|
+
const path = require('node:path');
|
|
12
|
+
const fs = require('node:fs');
|
|
13
|
+
const ts = require('typescript');
|
|
14
|
+
|
|
15
|
+
const TSCONFIG = 'tsconfig.angular.json';
|
|
16
|
+
const metroArgs = process.argv.slice(2);
|
|
17
|
+
const projectRoot = process.cwd();
|
|
18
|
+
|
|
19
|
+
// perform_watch.js chokidar-watches angularCompilerOptions.basePath recursively (filtered only
|
|
20
|
+
// by a hardcoded node_modules/.dotfiles/.js/.map/.metadata.json regex — never ios/android/build),
|
|
21
|
+
// so an app's tsconfig.angular.json narrows basePath to its own src/ to keep the native platform
|
|
22
|
+
// trees out of the watch (see that file's own comment for the EMFILE story this fixes). That
|
|
23
|
+
// value is written relative (portable, checked in) — but @angular/compiler-cli's INCREMENTAL
|
|
24
|
+
// recompile path (oldProgram reuse, only reachable once `ngc --watch` is already running) calls
|
|
25
|
+
// absoluteFrom() on basePath directly and throws "TS500: ... path is not absolute" if it isn't
|
|
26
|
+
// already absolute, even though the initial cold compile tolerates a relative one fine. Resolve
|
|
27
|
+
// it here, at spawn time, into a throwaway override config — the checked-in tsconfig itself never
|
|
28
|
+
// carries a machine-specific absolute path.
|
|
29
|
+
function resolveWatchTsconfig(tsconfigName) {
|
|
30
|
+
const realPath = path.resolve(projectRoot, tsconfigName);
|
|
31
|
+
const { config, error } = ts.readConfigFile(realPath, ts.sys.readFile);
|
|
32
|
+
const basePath = config?.angularCompilerOptions?.basePath;
|
|
33
|
+
if (error || typeof basePath !== 'string' || path.isAbsolute(basePath)) {
|
|
34
|
+
return realPath;
|
|
35
|
+
}
|
|
36
|
+
// Written inside the project (build/, already gitignored everywhere this script runs) rather
|
|
37
|
+
// than os.tmpdir() — TS resolves default typeRoots/@types by walking up from the extending
|
|
38
|
+
// config's OWN directory, and a tmpdir has no node_modules above it, so an os.tmpdir() location
|
|
39
|
+
// broke `@types/node` resolution (TS2688) even though the extended real config was found fine.
|
|
40
|
+
const buildDir = path.resolve(projectRoot, 'build');
|
|
41
|
+
fs.mkdirSync(buildDir, { recursive: true });
|
|
42
|
+
const watchConfigPath = path.join(buildDir, `symbiote-angular-dev-watch-${process.pid}.json`);
|
|
43
|
+
fs.writeFileSync(
|
|
44
|
+
watchConfigPath,
|
|
45
|
+
JSON.stringify({
|
|
46
|
+
extends: realPath,
|
|
47
|
+
angularCompilerOptions: { basePath: path.resolve(projectRoot, basePath) },
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
return watchConfigPath;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Without watchman, Metro falls back to chokidar's native fs.watch, which opens one OS file
|
|
54
|
+
// handle per watched directory. This project's watchFolders spans the whole monorepo, so that
|
|
55
|
+
// reliably blows past macOS's per-process fd limit (EMFILE) — doubly likely here since ngc
|
|
56
|
+
// --watch adds a second watcher on top of Metro's own. Warn instead of letting everyone
|
|
57
|
+
// individually debug a native stack trace down to this one missing binary.
|
|
58
|
+
const watchmanCheck = spawnSync('watchman', ['--version'], { stdio: 'ignore', shell: true });
|
|
59
|
+
if (watchmanCheck.status !== 0) {
|
|
60
|
+
console.warn(
|
|
61
|
+
'[symbiote-angular-dev] watchman not found on PATH. Metro will fall back to watching files ' +
|
|
62
|
+
'itself, which commonly crashes with "EMFILE: too many open files" on a repo this size. ' +
|
|
63
|
+
'Install it: https://facebook.github.io/watchman/docs/install (macOS: brew install watchman).',
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const initialBuild = spawnSync('ngc', ['-p', TSCONFIG], { stdio: 'inherit', shell: true });
|
|
68
|
+
if (initialBuild.status !== 0) {
|
|
69
|
+
process.exit(initialBuild.status ?? 1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const watchTsconfigPath = resolveWatchTsconfig(TSCONFIG);
|
|
73
|
+
const ngcWatch = spawn('ngc', ['-p', watchTsconfigPath, '--watch'], { stdio: 'inherit', shell: true });
|
|
74
|
+
const metro = spawn('react-native', ['start', ...metroArgs], { stdio: 'inherit', shell: true });
|
|
75
|
+
|
|
76
|
+
function stopNgcWatch() {
|
|
77
|
+
ngcWatch.kill();
|
|
78
|
+
if (watchTsconfigPath !== path.resolve(projectRoot, TSCONFIG)) {
|
|
79
|
+
fs.rmSync(watchTsconfigPath, { force: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
metro.on('exit', (code) => {
|
|
84
|
+
stopNgcWatch();
|
|
85
|
+
process.exit(code ?? 0);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
89
|
+
process.on(signal, () => {
|
|
90
|
+
stopNgcWatch();
|
|
91
|
+
metro.kill(signal);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Registry of composed-component selectors that must NOT paint a native view of their own.
|
|
2
|
+
//
|
|
3
|
+
// A dependency-free LEAF module (imports nothing from the adapter barrel `./index` or
|
|
4
|
+
// `./components`, both deeply require-cyclic). Both consumers reach it by RELATIVE path — the
|
|
5
|
+
// renderer imports `isAnchorHostComponent` from `../anchor-host-registry`, the barrel re-exports
|
|
6
|
+
// `registerComposedComponent` from `./anchor-host-registry` — so Metro keys it to ONE module
|
|
7
|
+
// instance / ONE Set. Do NOT give it a package `exports` subpath and inject THAT bare specifier
|
|
8
|
+
// into app code: a subpath resolves via a different path than the relative imports under pnpm
|
|
9
|
+
// symlinks, which splits the Set in two.
|
|
10
|
+
//
|
|
11
|
+
// Housing the registry here rather than inline in `renderer/index.ts` keeps it out of the require
|
|
12
|
+
// cycle (cheap insurance against a load-order strand). The bug that actually surfaced this,
|
|
13
|
+
// though, was STALE BUILD ARTIFACTS, not the cycle: `ngc -p` never deletes orphaned outputs, so
|
|
14
|
+
// after the renderer moved `renderer.ts` → `renderer/index.ts` the orphaned `build/angular/
|
|
15
|
+
// renderer.js` lingered and SHADOWED `build/angular/renderer/index.js` (a file beats a folder in
|
|
16
|
+
// Node/Metro resolution), giving the bundle a second, stale registry Set — fixed by cleaning
|
|
17
|
+
// `build/` before every ngc build (see each Angular package's `clean` script). Full record:
|
|
18
|
+
// angular-adapter §11c, symbiote-dev-examples §5e.
|
|
19
|
+
// Lowercased at construction — isAnchorHostComponent and registerComposedComponent both normalize
|
|
20
|
+
// to lowercase (Angular lowercases a dynamically-mounted component's selector at runtime, see
|
|
21
|
+
// angular-adapter §11a), so the literal entries below must match that or every capitalized one
|
|
22
|
+
// (all but the handful already written lowercase) silently never matches .has() and falls through
|
|
23
|
+
// to a real Fabric createNode — the exact "Unimplemented component" / extra-wrapper-node bug this
|
|
24
|
+
// Set exists to prevent.
|
|
25
|
+
const ANCHOR_HOST_COMPONENTS = new Set([
|
|
26
|
+
// Composed Angular components render their real Fabric descriptor tree from the template;
|
|
27
|
+
// their Angular host element is only a framework bookkeeping node and must not paint. This
|
|
28
|
+
// is NOT limited to adapter-authored components — ANY custom composed @Component used as a
|
|
29
|
+
// plain <Tag> inside another template needs its selector listed here too, or Angular's
|
|
30
|
+
// automatic host-element creation for it falls through to a raw Fabric createNode call with
|
|
31
|
+
// an unrecognized view name, which paints RN's own "Unimplemented component: <Tag>" fallback
|
|
32
|
+
// view instead (a real device-visible bug, not a silent no-op). This Set holds only
|
|
33
|
+
// adapter/engine-owned selectors; app code and third-party packages self-register their own
|
|
34
|
+
// composed components through registerComposedComponent instead of being hardcoded here.
|
|
35
|
+
'ActivityIndicator',
|
|
36
|
+
'Button',
|
|
37
|
+
'FlatList',
|
|
38
|
+
'AnimatedView',
|
|
39
|
+
'symbiote-animated-view',
|
|
40
|
+
'AnimatedText',
|
|
41
|
+
'symbiote-animated-text',
|
|
42
|
+
'AnimatedImage',
|
|
43
|
+
'symbiote-animated-image',
|
|
44
|
+
'AnimatedScrollView',
|
|
45
|
+
'symbiote-animated-scroll-view',
|
|
46
|
+
'symbiote-descriptor-outlet',
|
|
47
|
+
'tunnel-out',
|
|
48
|
+
'Image',
|
|
49
|
+
'ImageBackground',
|
|
50
|
+
'InputAccessoryView',
|
|
51
|
+
'KeyboardAvoidingView',
|
|
52
|
+
'Modal',
|
|
53
|
+
'Pressable',
|
|
54
|
+
'RefreshControl',
|
|
55
|
+
'SafeAreaView',
|
|
56
|
+
'ScrollView',
|
|
57
|
+
'ScrollViewStickyHeader',
|
|
58
|
+
'SectionList',
|
|
59
|
+
'symbiote-sticky-header',
|
|
60
|
+
'StatusBar',
|
|
61
|
+
'Switch',
|
|
62
|
+
'Text',
|
|
63
|
+
'TextInput',
|
|
64
|
+
'TouchableHighlight',
|
|
65
|
+
'TouchableNativeFeedback',
|
|
66
|
+
'TouchableOpacity',
|
|
67
|
+
'TouchableWithoutFeedback',
|
|
68
|
+
'VirtualizedList',
|
|
69
|
+
'VirtualizedSectionList',
|
|
70
|
+
'symbiote-pressable',
|
|
71
|
+
].map(selector => selector.toLowerCase()));
|
|
72
|
+
// A composed component's selector must be registered so createElement gives it a non-painting
|
|
73
|
+
// anchor host (see the Set comment above). Tests register their own child-component selectors
|
|
74
|
+
// through this at module load; app-authored composed components self-register the same way via
|
|
75
|
+
// the babel-register-composed plugin.
|
|
76
|
+
export function registerComposedComponent(selector) {
|
|
77
|
+
ANCHOR_HOST_COMPONENTS.add(selector.toLowerCase());
|
|
78
|
+
}
|
|
79
|
+
// True when `engineName` is a composed selector that must anchor-host (not paint). Case-
|
|
80
|
+
// insensitive — the Set is lowercased at construction, so callers pass the raw selector.
|
|
81
|
+
export function isAnchorHostComponent(engineName) {
|
|
82
|
+
return ANCHOR_HOST_COMPONENTS.has(engineName.toLowerCase());
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=anchor-host-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor-host-registry.js","sourceRoot":"","sources":["../../src/anchor-host-registry.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,EAAE;AACF,sFAAsF;AACtF,8FAA8F;AAC9F,iGAAiG;AACjG,6FAA6F;AAC7F,gGAAgG;AAChG,8FAA8F;AAC9F,yCAAyC;AACzC,EAAE;AACF,kGAAkG;AAClG,4FAA4F;AAC5F,gGAAgG;AAChG,4FAA4F;AAC5F,iGAAiG;AACjG,6FAA6F;AAC7F,4FAA4F;AAC5F,mDAAmD;AAEnD,kGAAkG;AAClG,8FAA8F;AAC9F,+FAA+F;AAC/F,kGAAkG;AAClG,kGAAkG;AAClG,yBAAyB;AACzB,MAAM,sBAAsB,GAAgB,IAAI,GAAG,CACjD;IACE,0FAA0F;IAC1F,2FAA2F;IAC3F,2FAA2F;IAC3F,uFAAuF;IACvF,4FAA4F;IAC5F,6FAA6F;IAC7F,oFAAoF;IACpF,4FAA4F;IAC5F,yFAAyF;IACzF,mBAAmB;IACnB,QAAQ;IACR,UAAU;IACV,cAAc;IACd,wBAAwB;IACxB,cAAc;IACd,wBAAwB;IACxB,eAAe;IACf,yBAAyB;IACzB,oBAAoB;IACpB,+BAA+B;IAC/B,4BAA4B;IAC5B,YAAY;IACZ,OAAO;IACP,iBAAiB;IACjB,oBAAoB;IACpB,sBAAsB;IACtB,OAAO;IACP,WAAW;IACX,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,wBAAwB;IACxB,aAAa;IACb,wBAAwB;IACxB,WAAW;IACX,QAAQ;IACR,MAAM;IACN,WAAW;IACX,oBAAoB;IACpB,yBAAyB;IACzB,kBAAkB;IAClB,0BAA0B;IAC1B,iBAAiB;IACjB,wBAAwB;IACxB,oBAAoB;CACrB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAC1C,CAAC;AAEF,8FAA8F;AAC9F,8FAA8F;AAC9F,+FAA+F;AAC/F,sCAAsC;AACtC,MAAM,UAAU,yBAAyB,CAAC,QAAgB;IACxD,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,yFAAyF;AACzF,yFAAyF;AACzF,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACtD,OAAO,sBAAsB,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Type } from '@angular/core';
|
|
2
|
+
import { type IBootstrapHostOptions } from '@symbiote-native/components/bootstrap';
|
|
3
|
+
export type { IBootstrapHostOptions } from '@symbiote-native/components/bootstrap';
|
|
4
|
+
export type IBootstrapApplicationOptions = IBootstrapHostOptions & {
|
|
5
|
+
appName: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function bootstrapApplication(AppComponent: Type<unknown>, options: IBootstrapApplicationOptions): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Zero-config app entry, the Angular twin of adapters/react/src/bootstrap.ts. Lives OUTSIDE the
|
|
2
|
+
// package's main barrel — see that file's header for why anything importing react-native must
|
|
3
|
+
// stay there. No @Component/@Directive decorators here, so unlike the package's main "." entry
|
|
4
|
+
// this needs no ngc/AOT build step and can stay a plain source reference.
|
|
5
|
+
import { AppRegistry as RNAppRegistry } from 'react-native';
|
|
6
|
+
import { bootstrapHost } from '@symbiote-native/components/bootstrap';
|
|
7
|
+
import { AppRegistry, setHostRegistrar } from './modules/app-registry';
|
|
8
|
+
// Mirrors real Angular's bootstrapApplication(RootComponent, config) idiom.
|
|
9
|
+
export function bootstrapApplication(AppComponent, options) {
|
|
10
|
+
const { appName, ...bootstrapOptions } = options;
|
|
11
|
+
bootstrapHost(bootstrapOptions);
|
|
12
|
+
setHostRegistrar(RNAppRegistry);
|
|
13
|
+
AppRegistry.registerComponent(appName, () => AppComponent);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/bootstrap.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8FAA8F;AAC9F,+FAA+F;AAC/F,0EAA0E;AAE1E,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,aAAa,EAA8B,MAAM,uCAAuC,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAQvE,4EAA4E;AAC5E,MAAM,UAAU,oBAAoB,CAClC,YAA2B,EAC3B,OAAqC;IAErC,MAAM,EAAE,OAAO,EAAE,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAC;IACjD,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAChC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAChC,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ActivityIndicatorBase } from './shared';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export type { IActivityIndicatorProps } from './shared';
|
|
4
|
+
export declare class ActivityIndicator extends ActivityIndicatorBase {
|
|
5
|
+
protected readonly defaultColor: null;
|
|
6
|
+
protected readonly nativeExtras: {
|
|
7
|
+
styleAttr: string;
|
|
8
|
+
indeterminate: boolean;
|
|
9
|
+
};
|
|
10
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ActivityIndicator, never>;
|
|
11
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ActivityIndicator, "ActivityIndicator", never, {}, {}, never, never, true, never>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { DescriptorOutlet } from '../../descriptor-to-angular';
|
|
3
|
+
import { ActivityIndicatorBase } from './shared';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export class ActivityIndicator extends ActivityIndicatorBase {
|
|
6
|
+
defaultColor = null;
|
|
7
|
+
nativeExtras = { styleAttr: 'Normal', indeterminate: true };
|
|
8
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ActivityIndicator, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
9
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: ActivityIndicator, isStandalone: true, selector: "ActivityIndicator", usesInheritance: true, ngImport: i0, template: `<symbiote-descriptor-outlet [node]="descriptor" />`, isInline: true, dependencies: [{ kind: "component", type: DescriptorOutlet, selector: "symbiote-descriptor-outlet", inputs: ["node"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10
|
+
}
|
|
11
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ActivityIndicator, decorators: [{
|
|
12
|
+
type: Component,
|
|
13
|
+
args: [{
|
|
14
|
+
selector: 'ActivityIndicator',
|
|
15
|
+
standalone: true,
|
|
16
|
+
imports: [DescriptorOutlet],
|
|
17
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
18
|
+
template: `<symbiote-descriptor-outlet [node]="descriptor" />`,
|
|
19
|
+
}]
|
|
20
|
+
}] });
|
|
21
|
+
//# sourceMappingURL=index.android.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.android.js","sourceRoot":"","sources":["../../../../src/components/activity-indicator/index.android.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;;AAUjD,MAAM,OAAO,iBAAkB,SAAQ,qBAAqB;IACvC,YAAY,GAAG,IAAI,CAAC;IACX,YAAY,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;uGAF7E,iBAAiB;2FAAjB,iBAAiB,oGAFlB,oDAAoD,4DAFpD,gBAAgB;;2FAIf,iBAAiB;kBAP7B,SAAS;mBAAC;oBACT,QAAQ,EAAE,mBAAmB;oBAC7B,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,gBAAgB,CAAC;oBAC3B,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,QAAQ,EAAE,oDAAoD;iBAC/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './index.ios';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ActivityIndicatorBase } from './shared';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export type { IActivityIndicatorProps } from './shared';
|
|
4
|
+
export declare class ActivityIndicator extends ActivityIndicatorBase {
|
|
5
|
+
protected readonly defaultColor = "#999999";
|
|
6
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ActivityIndicator, never>;
|
|
7
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ActivityIndicator, "ActivityIndicator", never, {}, {}, never, never, true, never>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { DescriptorOutlet } from '../../descriptor-to-angular';
|
|
3
|
+
import { ActivityIndicatorBase } from './shared';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
const IOS_DEFAULT_COLOR = '#999999';
|
|
6
|
+
export class ActivityIndicator extends ActivityIndicatorBase {
|
|
7
|
+
defaultColor = IOS_DEFAULT_COLOR;
|
|
8
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ActivityIndicator, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
9
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: ActivityIndicator, isStandalone: true, selector: "ActivityIndicator", usesInheritance: true, ngImport: i0, template: `<symbiote-descriptor-outlet [node]="descriptor" />`, isInline: true, dependencies: [{ kind: "component", type: DescriptorOutlet, selector: "symbiote-descriptor-outlet", inputs: ["node"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10
|
+
}
|
|
11
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ActivityIndicator, decorators: [{
|
|
12
|
+
type: Component,
|
|
13
|
+
args: [{
|
|
14
|
+
selector: 'ActivityIndicator',
|
|
15
|
+
standalone: true,
|
|
16
|
+
imports: [DescriptorOutlet],
|
|
17
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
18
|
+
template: `<symbiote-descriptor-outlet [node]="descriptor" />`,
|
|
19
|
+
}]
|
|
20
|
+
}] });
|
|
21
|
+
//# sourceMappingURL=index.ios.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.ios.js","sourceRoot":"","sources":["../../../../src/components/activity-indicator/index.ios.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;;AAGjD,MAAM,iBAAiB,GAAG,SAAS,CAAC;AASpC,MAAM,OAAO,iBAAkB,SAAQ,qBAAqB;IACvC,YAAY,GAAG,iBAAiB,CAAC;uGADzC,iBAAiB;2FAAjB,iBAAiB,oGAFlB,oDAAoD,4DAFpD,gBAAgB;;2FAIf,iBAAiB;kBAP7B,SAAS;mBAAC;oBACT,QAAQ,EAAE,mBAAmB;oBAC7B,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,gBAAgB,CAAC;oBAC3B,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,QAAQ,EAAE,oDAAoD;iBAC/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/activity-indicator/index.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,wCAAwC;AAExC,cAAc,aAAa,CAAC"}
|