@symbiote-native/angular 0.1.0
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 +147 -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/drawer-layout-android/index.android.d.ts +34 -0
- package/build/angular/components/drawer-layout-android/index.android.js +291 -0
- package/build/angular/components/drawer-layout-android/index.android.js.map +1 -0
- package/build/angular/components/drawer-layout-android/index.d.ts +11 -0
- package/build/angular/components/drawer-layout-android/index.js +109 -0
- package/build/angular/components/drawer-layout-android/index.js.map +1 -0
- package/build/angular/components/drawer-layout-android/shared.d.ts +74 -0
- package/build/angular/components/drawer-layout-android/shared.js +138 -0
- package/build/angular/components/drawer-layout-android/shared.js.map +1 -0
- package/build/angular/components/flat-list/index.d.ts +122 -0
- package/build/angular/components/flat-list/index.js +689 -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 +408 -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.d.ts +59 -0
- package/build/angular/components/input-accessory-view.js +266 -0
- package/build/angular/components/input-accessory-view.js.map +1 -0
- package/build/angular/components/keyboard-avoiding-view.d.ts +82 -0
- package/build/angular/components/keyboard-avoiding-view.js +363 -0
- package/build/angular/components/keyboard-avoiding-view.js.map +1 -0
- package/build/angular/components/modal.d.ts +92 -0
- package/build/angular/components/modal.js +365 -0
- package/build/angular/components/modal.js.map +1 -0
- package/build/angular/components/pressable/index.d.ts +123 -0
- package/build/angular/components/pressable/index.js +421 -0
- package/build/angular/components/pressable/index.js.map +1 -0
- package/build/angular/components/refresh-control.d.ts +86 -0
- package/build/angular/components/refresh-control.js +347 -0
- package/build/angular/components/refresh-control.js.map +1 -0
- package/build/angular/components/safe-area-view.d.ts +57 -0
- package/build/angular/components/safe-area-view.js +253 -0
- package/build/angular/components/safe-area-view.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 +312 -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 +679 -0
- package/build/angular/components/scroll-view/shared.js.map +1 -0
- package/build/angular/components/scroll-view/sticky-header.d.ts +41 -0
- package/build/angular/components/scroll-view/sticky-header.js +208 -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 +604 -0
- package/build/angular/components/text-input.js.map +1 -0
- package/build/angular/components/touchable-native-feedback.d.ts +83 -0
- package/build/angular/components/touchable-native-feedback.js +376 -0
- package/build/angular/components/touchable-native-feedback.js.map +1 -0
- package/build/angular/components/touchable.d.ts +248 -0
- package/build/angular/components/touchable.js +1206 -0
- package/build/angular/components/touchable.js.map +1 -0
- package/build/angular/components/virtualized-list/directives.d.ts +54 -0
- package/build/angular/components/virtualized-list/directives.js +154 -0
- package/build/angular/components/virtualized-list/directives.js.map +1 -0
- package/build/angular/components/virtualized-list/index.d.ts +268 -0
- package/build/angular/components/virtualized-list/index.js +1162 -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 +77 -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 +722 -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.d.ts +22 -0
- package/build/angular/create-portal.js +74 -0
- package/build/angular/create-portal.js.map +1 -0
- package/build/angular/create-tunnel.d.ts +34 -0
- package/build/angular/create-tunnel.js +126 -0
- package/build/angular/create-tunnel.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 +21 -0
- package/build/angular/index.js +42 -0
- package/build/angular/index.js.map +1 -0
- package/build/angular/modules/animated/create-animated-component.d.ts +68 -0
- package/build/angular/modules/animated/create-animated-component.js +429 -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.d.ts +20 -0
- package/build/angular/modules/status-bar.js +59 -0
- package/build/angular/modules/status-bar.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 +89 -0
- package/build/angular/primitives/shared.js +172 -0
- package/build/angular/primitives/shared.js.map +1 -0
- package/build/angular/render.d.ts +11 -0
- package/build/angular/render.js +161 -0
- package/build/angular/render.js.map +1 -0
- package/build/angular/renderer.d.ts +38 -0
- package/build/angular/renderer.js +360 -0
- package/build/angular/renderer.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/build/components/activity-indicator/index.android.d.ts +9 -0
- package/build/components/activity-indicator/index.android.js +64 -0
- package/build/components/activity-indicator/index.d.ts +1 -0
- package/build/components/activity-indicator/index.ios.d.ts +5 -0
- package/build/components/activity-indicator/index.ios.js +64 -0
- package/build/components/activity-indicator/index.js +3 -0
- package/build/components/activity-indicator/shared.d.ts +64 -0
- package/build/components/activity-indicator/shared.js +424 -0
- package/build/components/button.d.ts +60 -0
- package/build/components/button.js +456 -0
- package/build/components/drawer-layout-android/index.android.d.ts +29 -0
- package/build/components/drawer-layout-android/index.android.js +326 -0
- package/build/components/drawer-layout-android/index.d.ts +8 -0
- package/build/components/drawer-layout-android/index.js +145 -0
- package/build/components/drawer-layout-android/shared.d.ts +71 -0
- package/build/components/drawer-layout-android/shared.js +205 -0
- package/build/components/flat-list/index.d.ts +119 -0
- package/build/components/flat-list/index.js +692 -0
- package/build/components/image/index.android.d.ts +7 -0
- package/build/components/image/index.android.js +88 -0
- package/build/components/image/index.d.ts +1 -0
- package/build/components/image/index.ios.d.ts +7 -0
- package/build/components/image/index.ios.js +88 -0
- package/build/components/image/index.js +2 -0
- package/build/components/image/shared.d.ts +101 -0
- package/build/components/image/shared.js +407 -0
- package/build/components/image-background.d.ts +78 -0
- package/build/components/image-background.js +583 -0
- package/build/components/input-accessory-view.d.ts +56 -0
- package/build/components/input-accessory-view.js +407 -0
- package/build/components/keyboard-avoiding-view.d.ts +79 -0
- package/build/components/keyboard-avoiding-view.js +509 -0
- package/build/components/modal.d.ts +89 -0
- package/build/components/modal.js +534 -0
- package/build/components/pressable/index.d.ts +120 -0
- package/build/components/pressable/index.js +640 -0
- package/build/components/refresh-control.d.ts +83 -0
- package/build/components/refresh-control.js +514 -0
- package/build/components/safe-area-view.d.ts +54 -0
- package/build/components/safe-area-view.js +393 -0
- package/build/components/scroll-view/index.android.d.ts +16 -0
- package/build/components/scroll-view/index.android.js +228 -0
- package/build/components/scroll-view/index.d.ts +3 -0
- package/build/components/scroll-view/index.ios.d.ts +6 -0
- package/build/components/scroll-view/index.ios.js +113 -0
- package/build/components/scroll-view/index.js +5 -0
- package/build/components/scroll-view/projection.d.ts +32 -0
- package/build/components/scroll-view/projection.js +311 -0
- package/build/components/scroll-view/shared.d.ts +225 -0
- package/build/components/scroll-view/shared.js +757 -0
- package/build/components/scroll-view/sticky-header.d.ts +38 -0
- package/build/components/scroll-view/sticky-header.js +257 -0
- package/build/components/section-list/index.d.ts +113 -0
- package/build/components/section-list/index.js +768 -0
- package/build/components/switch/index.android.d.ts +17 -0
- package/build/components/switch/index.android.js +107 -0
- package/build/components/switch/index.d.ts +1 -0
- package/build/components/switch/index.ios.d.ts +16 -0
- package/build/components/switch/index.ios.js +106 -0
- package/build/components/switch/index.js +3 -0
- package/build/components/switch/shared.d.ts +37 -0
- package/build/components/switch/shared.js +176 -0
- package/build/components/text-input.d.ts +150 -0
- package/build/components/text-input.js +826 -0
- package/build/components/touchable-native-feedback.d.ts +80 -0
- package/build/components/touchable-native-feedback.js +550 -0
- package/build/components/touchable.d.ts +241 -0
- package/build/components/touchable.js +1672 -0
- package/build/components/virtualized-list/directives.d.ts +41 -0
- package/build/components/virtualized-list/directives.js +250 -0
- package/build/components/virtualized-list/index.d.ts +265 -0
- package/build/components/virtualized-list/index.js +1344 -0
- package/build/components/virtualized-section-list/directives.d.ts +28 -0
- package/build/components/virtualized-section-list/directives.js +149 -0
- package/build/components/virtualized-section-list/index.d.ts +175 -0
- package/build/components/virtualized-section-list/index.js +854 -0
- package/build/components.d.ts +39 -0
- package/build/components.js +37 -0
- package/build/create-portal.d.ts +17 -0
- package/build/create-portal.js +128 -0
- package/build/create-tunnel.d.ts +29 -0
- package/build/create-tunnel.js +181 -0
- package/build/descriptor-to-angular/index.d.ts +19 -0
- package/build/descriptor-to-angular/index.js +186 -0
- package/build/host-instance/index.d.ts +2 -0
- package/build/host-instance/index.js +36 -0
- package/build/index.d.ts +21 -0
- package/build/index.js +41 -0
- package/build/modules/animated/create-animated-component.d.ts +57 -0
- package/build/modules/animated/create-animated-component.js +490 -0
- package/build/modules/animated/index.d.ts +51 -0
- package/build/modules/animated/index.js +58 -0
- package/build/modules/app-registry/index.d.ts +7 -0
- package/build/modules/app-registry/index.js +22 -0
- package/build/modules/status-bar.d.ts +17 -0
- package/build/modules/status-bar.js +121 -0
- package/build/primitives/index.d.ts +32 -0
- package/build/primitives/index.js +386 -0
- package/build/primitives/shared.d.ts +84 -0
- package/build/primitives/shared.js +231 -0
- package/build/render.d.ts +11 -0
- package/build/render.js +160 -0
- package/build/renderer.d.ts +38 -0
- package/build/renderer.js +359 -0
- package/build/services/color-scheme.service.d.ts +13 -0
- package/build/services/color-scheme.service.js +72 -0
- package/build/services/index.d.ts +2 -0
- package/build/services/index.js +2 -0
- package/build/services/window-dimensions.service.d.ts +13 -0
- package/build/services/window-dimensions.service.js +83 -0
- package/metro-css-parser.cjs +11 -0
- package/package.json +57 -0
- package/src/__tests__/responder-change-detection.test.ts +102 -0
- package/src/__tests__/responder-nested-cd.test.ts +113 -0
- package/src/angular-gaps.test.ts +142 -0
- package/src/angular-imports.test.ts +100 -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 +575 -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 +478 -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.test.ts +43 -0
- package/src/components/input-accessory-view.ts +191 -0
- package/src/components/keyboard-avoiding-view.test.ts +54 -0
- package/src/components/keyboard-avoiding-view.ts +308 -0
- package/src/components/modal.test.ts +43 -0
- package/src/components/modal.ts +304 -0
- package/src/components/pressable/index.ts +371 -0
- package/src/components/pressable/pressable.test.ts +85 -0
- package/src/components/refresh-control.test.ts +41 -0
- package/src/components/refresh-control.ts +288 -0
- package/src/components/safe-area-view.test.ts +43 -0
- package/src/components/safe-area-view.ts +178 -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 +384 -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 +836 -0
- package/src/components/scroll-view/sticky-header.ts +230 -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 +536 -0
- package/src/components/touchable-native-feedback.test.ts +49 -0
- package/src/components/touchable-native-feedback.ts +260 -0
- package/src/components/touchable.test.ts +102 -0
- package/src/components/touchable.ts +643 -0
- package/src/components/virtualized-list/directives.ts +169 -0
- package/src/components/virtualized-list/index.ts +1204 -0
- package/src/components/virtualized-list/virtualized-list-class-style.test.ts +76 -0
- package/src/components/virtualized-section-list/directives.ts +91 -0
- package/src/components/virtualized-section-list/index.ts +598 -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.test.ts +90 -0
- package/src/create-portal.ts +74 -0
- package/src/create-tunnel.test.ts +120 -0
- package/src/create-tunnel.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 +257 -0
- package/src/modules/animated/animated-scroll-view.test.ts +85 -0
- package/src/modules/animated/create-animated-component.ts +435 -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.test.ts +50 -0
- package/src/modules/status-bar.ts +57 -0
- package/src/primitives/index.ts +119 -0
- package/src/primitives/shared.ts +191 -0
- package/src/render.test.ts +147 -0
- package/src/render.ts +224 -0
- package/src/renderer.test.ts +179 -0
- package/src/renderer.ts +407 -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
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// TouchableNativeFeedback: the Angular lifecycle half. Android's ripple / state-drawable
|
|
2
|
+
// touchable, built on Pressable like the rest of the family (the Angular twin of the React/Vue
|
|
3
|
+
// adapter). RN realizes its feedback by cloning the child into an RCTView carrying native ripple
|
|
4
|
+
// props; we instead nest the child under a feedback <symbiote-view> that carries those props
|
|
5
|
+
// (nativeBackgroundAndroid / nativeForegroundAndroid), inside a <Pressable> that owns the press
|
|
6
|
+
// wiring. The native props are read by Android's ReactViewManager; on iOS they are inert props,
|
|
7
|
+
// so the child still renders with working press wiring. The static factories + background mapping
|
|
8
|
+
// are shared in @symbiote-native/components and reused verbatim — Angular only attaches them onto the
|
|
9
|
+
// component class and nests the feedback view. No JS-side platform branch (one Fabric path both
|
|
10
|
+
// platforms), so this stays a flat single file (ADR 0026), mirroring React/Vue.
|
|
11
|
+
//
|
|
12
|
+
// This component's own press/hover events are now real @Output() EventEmitters too, matching
|
|
13
|
+
// Pressable (which it wraps) — `(press)="press.emit($event)"`, never `[onPress]="onPress"`.
|
|
14
|
+
// Non-event config (delayLongPress, hitSlop, ...) still rides down as plain @Input() bindings. The
|
|
15
|
+
// a11y identity bag + the four a11y events live on the feedback view — the one host intrinsic here —
|
|
16
|
+
// folded through the shared resolveAccessibilityProps and routed through emit() on the (event)
|
|
17
|
+
// channel (Angular blocks [onX] property bindings on host elements; events flow through (event)
|
|
18
|
+
// only). disabled folds into the a11y state via resolveDisabledAccessibilityState, exactly as
|
|
19
|
+
// Pressable does for its own host.
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
CUSTOM_ELEMENTS_SCHEMA,
|
|
23
|
+
ChangeDetectionStrategy,
|
|
24
|
+
Component,
|
|
25
|
+
ElementRef,
|
|
26
|
+
EventEmitter,
|
|
27
|
+
inject,
|
|
28
|
+
Input,
|
|
29
|
+
Output,
|
|
30
|
+
type OnChanges,
|
|
31
|
+
} from '@angular/core';
|
|
32
|
+
import {
|
|
33
|
+
backgroundProps,
|
|
34
|
+
canUseNativeForeground,
|
|
35
|
+
resolveAccessibilityProps,
|
|
36
|
+
resolveDisabledAccessibilityState,
|
|
37
|
+
rippleBackground,
|
|
38
|
+
selectableBackground,
|
|
39
|
+
selectableBackgroundBorderless,
|
|
40
|
+
type IAccessibilityProps,
|
|
41
|
+
type IAccessibilityStateValue,
|
|
42
|
+
type IAriaProps,
|
|
43
|
+
type INativeFeedbackBackground,
|
|
44
|
+
type IPressableAndroidRippleConfig,
|
|
45
|
+
type IRectOffset,
|
|
46
|
+
} from '@symbiote-native/components';
|
|
47
|
+
import { dlog, type ISymbioteEvent } from '@symbiote-native/engine';
|
|
48
|
+
import { anchorHostStyle, SymbioteHostPropsDirective, ViewHost } from '../primitives';
|
|
49
|
+
import { Pressable, type IAngularPressableInputs } from './pressable';
|
|
50
|
+
|
|
51
|
+
export type {
|
|
52
|
+
INativeFeedbackBackground,
|
|
53
|
+
IThemeAttrBackground,
|
|
54
|
+
IRippleBackground,
|
|
55
|
+
} from '@symbiote-native/components';
|
|
56
|
+
|
|
57
|
+
// Mirrors React's ITouchableNativeFeedbackProps (Omit<IPressableProps, 'style'> + the native
|
|
58
|
+
// feedback config) minus children (Angular takes children via <ng-content>) and minus the press/
|
|
59
|
+
// hover events (declared as this component's OWN @Output()s below). Declared per-adapter over the
|
|
60
|
+
// shared Pressable INPUT surface per <prop_types_split_agnostic_vs_per_adapter>.
|
|
61
|
+
export type IAngularTouchableNativeFeedbackProps = Omit<IAngularPressableInputs, 'style'> & {
|
|
62
|
+
background?: INativeFeedbackBackground;
|
|
63
|
+
useForeground?: boolean;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Angular infers an `(event)` binding's $event as the DOM Event for a custom-schema element,
|
|
67
|
+
// so each handler enters as `unknown` and is narrowed here before reaching a typed callback.
|
|
68
|
+
function isSymbioteEvent(value: unknown): value is ISymbioteEvent {
|
|
69
|
+
return typeof value === 'object' && value !== null && 'nativeEvent' in value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@Component({
|
|
73
|
+
selector: 'TouchableNativeFeedback',
|
|
74
|
+
standalone: true,
|
|
75
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
76
|
+
imports: [Pressable, ViewHost, SymbioteHostPropsDirective],
|
|
77
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
78
|
+
template: `
|
|
79
|
+
<Pressable
|
|
80
|
+
(press)="press.emit($event)"
|
|
81
|
+
(pressIn)="pressIn.emit($event)"
|
|
82
|
+
(pressOut)="pressOut.emit($event)"
|
|
83
|
+
(pressMove)="pressMove.emit($event)"
|
|
84
|
+
(longPress)="longPress.emit($event)"
|
|
85
|
+
(hoverIn)="hoverIn.emit($event)"
|
|
86
|
+
(hoverOut)="hoverOut.emit($event)"
|
|
87
|
+
[delayLongPress]="delayLongPress"
|
|
88
|
+
[delayHoverIn]="delayHoverIn"
|
|
89
|
+
[delayHoverOut]="delayHoverOut"
|
|
90
|
+
[disabled]="disabled"
|
|
91
|
+
[cancelable]="cancelable"
|
|
92
|
+
[hitSlop]="hitSlop"
|
|
93
|
+
[pressRetentionOffset]="pressRetentionOffset"
|
|
94
|
+
[unstable_pressDelay]="unstable_pressDelay"
|
|
95
|
+
[android_ripple]="android_ripple"
|
|
96
|
+
[android_disableSound]="android_disableSound"
|
|
97
|
+
>
|
|
98
|
+
<symbiote-view
|
|
99
|
+
[symbioteHostProps]="hostProps"
|
|
100
|
+
(accessibilityAction)="emit(accessibilityAction, $event)"
|
|
101
|
+
(accessibilityTap)="emit(accessibilityTap, $event)"
|
|
102
|
+
(magicTap)="emit(magicTap, $event)"
|
|
103
|
+
(accessibilityEscape)="emit(accessibilityEscape, $event)"
|
|
104
|
+
>
|
|
105
|
+
<ng-content></ng-content>
|
|
106
|
+
</symbiote-view>
|
|
107
|
+
</Pressable>
|
|
108
|
+
`,
|
|
109
|
+
})
|
|
110
|
+
export class TouchableNativeFeedback implements IAngularTouchableNativeFeedbackProps, OnChanges {
|
|
111
|
+
// The static helpers are pure config-dict producers; they live as members on the component class
|
|
112
|
+
// so callers reach them as `TouchableNativeFeedback.Ripple(...)`, exactly like RN.
|
|
113
|
+
static readonly SelectableBackground = selectableBackground;
|
|
114
|
+
static readonly SelectableBackgroundBorderless = selectableBackgroundBorderless;
|
|
115
|
+
static readonly Ripple = rippleBackground;
|
|
116
|
+
static readonly canUseNativeForeground = canUseNativeForeground;
|
|
117
|
+
|
|
118
|
+
@Output() readonly press = new EventEmitter<ISymbioteEvent>();
|
|
119
|
+
@Output() readonly pressIn = new EventEmitter<ISymbioteEvent>();
|
|
120
|
+
@Output() readonly pressOut = new EventEmitter<ISymbioteEvent>();
|
|
121
|
+
@Output() readonly pressMove = new EventEmitter<ISymbioteEvent>();
|
|
122
|
+
@Output() readonly longPress = new EventEmitter<ISymbioteEvent>();
|
|
123
|
+
@Output() readonly hoverIn = new EventEmitter<ISymbioteEvent>();
|
|
124
|
+
@Output() readonly hoverOut = new EventEmitter<ISymbioteEvent>();
|
|
125
|
+
@Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
|
|
126
|
+
@Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
|
|
127
|
+
@Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
|
|
128
|
+
@Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
|
|
129
|
+
@Input() background?: INativeFeedbackBackground;
|
|
130
|
+
@Input() useForeground?: boolean;
|
|
131
|
+
@Input() delayLongPress?: number;
|
|
132
|
+
@Input() delayHoverIn?: number;
|
|
133
|
+
@Input() delayHoverOut?: number;
|
|
134
|
+
@Input() disabled?: boolean;
|
|
135
|
+
@Input() cancelable?: boolean;
|
|
136
|
+
@Input() hitSlop?: IRectOffset;
|
|
137
|
+
@Input() pressRetentionOffset?: IRectOffset;
|
|
138
|
+
@Input() unstable_pressDelay?: number;
|
|
139
|
+
@Input() android_ripple?: IPressableAndroidRippleConfig;
|
|
140
|
+
@Input() android_disableSound?: boolean;
|
|
141
|
+
@Input() testID?: string;
|
|
142
|
+
@Input() nativeID?: string;
|
|
143
|
+
@Input() accessible?: boolean;
|
|
144
|
+
@Input() accessibilityLabel?: string;
|
|
145
|
+
@Input() accessibilityHint?: string;
|
|
146
|
+
@Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
|
|
147
|
+
@Input() accessibilityState?: IAccessibilityStateValue;
|
|
148
|
+
@Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
|
|
149
|
+
@Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
|
|
150
|
+
@Input() accessibilityLabelledBy?: string | string[];
|
|
151
|
+
@Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
|
|
152
|
+
@Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
|
|
153
|
+
@Input() screenReaderFocusable?: boolean;
|
|
154
|
+
@Input() accessibilityViewIsModal?: boolean;
|
|
155
|
+
@Input() accessibilityElementsHidden?: boolean;
|
|
156
|
+
@Input() accessibilityIgnoresInvertColors?: boolean;
|
|
157
|
+
@Input() accessibilityLanguage?: string;
|
|
158
|
+
@Input() accessibilityRespondsToUserInteraction?: boolean;
|
|
159
|
+
@Input() accessibilityShowsLargeContentViewer?: boolean;
|
|
160
|
+
@Input() accessibilityLargeContentTitle?: string;
|
|
161
|
+
@Input() role?: IAriaProps['role'];
|
|
162
|
+
@Input('aria-label') ariaLabel?: string;
|
|
163
|
+
@Input('aria-labelledby') ariaLabelledBy?: string;
|
|
164
|
+
@Input('aria-live') ariaLive?: IAriaProps['aria-live'];
|
|
165
|
+
@Input('aria-hidden') ariaHidden?: boolean;
|
|
166
|
+
@Input('aria-busy') ariaBusy?: boolean;
|
|
167
|
+
@Input('aria-checked') ariaChecked?: boolean | 'mixed';
|
|
168
|
+
@Input('aria-disabled') ariaDisabled?: boolean;
|
|
169
|
+
@Input('aria-expanded') ariaExpanded?: boolean;
|
|
170
|
+
@Input('aria-selected') ariaSelected?: boolean;
|
|
171
|
+
@Input('aria-modal') ariaModal?: boolean;
|
|
172
|
+
@Input('aria-valuemax') ariaValueMax?: number;
|
|
173
|
+
@Input('aria-valuemin') ariaValueMin?: number;
|
|
174
|
+
@Input('aria-valuenow') ariaValueNow?: number;
|
|
175
|
+
@Input('aria-valuetext') ariaValueText?: string;
|
|
176
|
+
|
|
177
|
+
// This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
|
|
178
|
+
// onto (see anchorHostStyle's doc comment) — NOT the feedback <symbiote-view> one level down.
|
|
179
|
+
// TouchableNativeFeedback has no explicit `style`/`class`-forwarding @Input() of its own (RN's
|
|
180
|
+
// TouchableNativeFeedback takes none either — style/class always came from the child), so the
|
|
181
|
+
// anchor's class-derived style is the ONLY style source for hostProps.style below.
|
|
182
|
+
private readonly elementRef = inject(ElementRef);
|
|
183
|
+
|
|
184
|
+
ngOnChanges(): void {
|
|
185
|
+
dlog(
|
|
186
|
+
`TouchableNativeFeedback render ${this.resolvedBackground.type} useForeground ${this.useForeground === true}`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// RN defaults a missing background to SelectableBackground() so the touchable always shows
|
|
191
|
+
// feedback; mirror that here.
|
|
192
|
+
private get resolvedBackground(): INativeFeedbackBackground {
|
|
193
|
+
return this.background ?? selectableBackground();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// backgroundProps picks the foreground slot only where the platform supports it, else the
|
|
197
|
+
// background slot (canUseNativeForeground) — shared with React/Vue. One side is always undefined.
|
|
198
|
+
get feedback(): Record<string, INativeFeedbackBackground> {
|
|
199
|
+
return backgroundProps(this.resolvedBackground, this.useForeground === true);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Assembles the SAME resolved values the template used to bind one-by-one into a single
|
|
203
|
+
// flat bag for `[symbioteHostProps]` (Renderer2.setProperty per key) — see primitives/shared.ts.
|
|
204
|
+
get hostProps(): Record<string, unknown> {
|
|
205
|
+
return {
|
|
206
|
+
nativeBackgroundAndroid: this.feedback['nativeBackgroundAndroid'],
|
|
207
|
+
nativeForegroundAndroid: this.feedback['nativeForegroundAndroid'],
|
|
208
|
+
style: anchorHostStyle(this.elementRef),
|
|
209
|
+
testID: this.testID,
|
|
210
|
+
nativeID: this.nativeID,
|
|
211
|
+
accessible: this.accessible,
|
|
212
|
+
...this.folded,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Forward an engine event to the matching @Output(), narrowing the template's untyped $event.
|
|
217
|
+
emit(emitter: EventEmitter<ISymbioteEvent>, event: unknown): void {
|
|
218
|
+
if (isSymbioteEvent(event)) emitter.emit(event);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Fold the web aria-*/role aliases into the canonical accessibility* props once per render, so the
|
|
222
|
+
// host never sees an aria-* key (native ignores them), and merge `disabled` into the a11y state
|
|
223
|
+
// (resolveDisabledAccessibilityState) the same way Pressable does for its own host.
|
|
224
|
+
get folded(): Partial<IAngularTouchableNativeFeedbackProps> {
|
|
225
|
+
return resolveAccessibilityProps({
|
|
226
|
+
accessibilityLabel: this.accessibilityLabel,
|
|
227
|
+
accessibilityHint: this.accessibilityHint,
|
|
228
|
+
accessibilityRole: this.accessibilityRole,
|
|
229
|
+
accessibilityState: resolveDisabledAccessibilityState(this.accessibilityState, this.disabled),
|
|
230
|
+
accessibilityValue: this.accessibilityValue,
|
|
231
|
+
accessibilityActions: this.accessibilityActions,
|
|
232
|
+
accessibilityLabelledBy: this.accessibilityLabelledBy,
|
|
233
|
+
importantForAccessibility: this.importantForAccessibility,
|
|
234
|
+
accessibilityLiveRegion: this.accessibilityLiveRegion,
|
|
235
|
+
screenReaderFocusable: this.screenReaderFocusable,
|
|
236
|
+
accessibilityViewIsModal: this.accessibilityViewIsModal,
|
|
237
|
+
accessibilityElementsHidden: this.accessibilityElementsHidden,
|
|
238
|
+
accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
|
|
239
|
+
accessibilityLanguage: this.accessibilityLanguage,
|
|
240
|
+
accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
|
|
241
|
+
accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
|
|
242
|
+
accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
|
|
243
|
+
role: this.role,
|
|
244
|
+
'aria-label': this.ariaLabel,
|
|
245
|
+
'aria-labelledby': this.ariaLabelledBy,
|
|
246
|
+
'aria-live': this.ariaLive,
|
|
247
|
+
'aria-hidden': this.ariaHidden,
|
|
248
|
+
'aria-busy': this.ariaBusy,
|
|
249
|
+
'aria-checked': this.ariaChecked,
|
|
250
|
+
'aria-disabled': this.ariaDisabled,
|
|
251
|
+
'aria-expanded': this.ariaExpanded,
|
|
252
|
+
'aria-selected': this.ariaSelected,
|
|
253
|
+
'aria-modal': this.ariaModal,
|
|
254
|
+
'aria-valuemax': this.ariaValueMax,
|
|
255
|
+
'aria-valuemin': this.ariaValueMin,
|
|
256
|
+
'aria-valuenow': this.ariaValueNow,
|
|
257
|
+
'aria-valuetext': this.ariaValueText,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Regression coverage for the anchor-vs-real-content class bug (see pressable.test.ts for the
|
|
2
|
+
// full writeup): a `class="..."` written on a composed component's OWN use site always resolves
|
|
3
|
+
// through Angular's addClass/removeClass onto that component's non-painting ANCHOR host, never
|
|
4
|
+
// onto the real committed Fabric view one (or more) levels down. Each Touchable forwards its own
|
|
5
|
+
// anchor's resolved style into whatever it commits, mirroring Pressable's fix.
|
|
6
|
+
import '@angular/compiler';
|
|
7
|
+
import { Component } from '@angular/core';
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
9
|
+
import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
|
|
10
|
+
import { installFabric } from '@symbiote-native/test-utils';
|
|
11
|
+
|
|
12
|
+
import { mount, unmount } from '../render';
|
|
13
|
+
import { TouchableHighlight, TouchableOpacity, TouchableWithoutFeedback } from './touchable';
|
|
14
|
+
|
|
15
|
+
const ROOT_TAG = 940;
|
|
16
|
+
const fabric = installFabric();
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
fabric.reset();
|
|
20
|
+
});
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
unmount(ROOT_TAG);
|
|
23
|
+
clearGlobalStyles();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
@Component({
|
|
27
|
+
selector: 'symbiote-touchable-opacity-host',
|
|
28
|
+
standalone: true,
|
|
29
|
+
imports: [TouchableOpacity],
|
|
30
|
+
template: `
|
|
31
|
+
<TouchableOpacity [testID]="'opacity'" class="card">
|
|
32
|
+
<symbiote-text>Press</symbiote-text>
|
|
33
|
+
</TouchableOpacity>
|
|
34
|
+
`,
|
|
35
|
+
})
|
|
36
|
+
class TouchableOpacityHost {}
|
|
37
|
+
|
|
38
|
+
@Component({
|
|
39
|
+
selector: 'symbiote-touchable-highlight-host',
|
|
40
|
+
standalone: true,
|
|
41
|
+
imports: [TouchableHighlight],
|
|
42
|
+
template: `
|
|
43
|
+
<TouchableHighlight [testID]="'highlight'" class="card">
|
|
44
|
+
<symbiote-text>Press</symbiote-text>
|
|
45
|
+
</TouchableHighlight>
|
|
46
|
+
`,
|
|
47
|
+
})
|
|
48
|
+
class TouchableHighlightHost {}
|
|
49
|
+
|
|
50
|
+
@Component({
|
|
51
|
+
selector: 'symbiote-touchable-without-feedback-host',
|
|
52
|
+
standalone: true,
|
|
53
|
+
imports: [TouchableWithoutFeedback],
|
|
54
|
+
template: `
|
|
55
|
+
<TouchableWithoutFeedback [testID]="'without-feedback'" class="card">
|
|
56
|
+
<symbiote-text>Press</symbiote-text>
|
|
57
|
+
</TouchableWithoutFeedback>
|
|
58
|
+
`,
|
|
59
|
+
})
|
|
60
|
+
class TouchableWithoutFeedbackHost {}
|
|
61
|
+
|
|
62
|
+
describe('TouchableOpacity', () => {
|
|
63
|
+
it('resolves a class= on the TouchableOpacity use site onto the real committed view, not the anchor', async () => {
|
|
64
|
+
registerStyles({ card: { backgroundColor: 'red' } });
|
|
65
|
+
|
|
66
|
+
mount(ROOT_TAG, TouchableOpacityHost);
|
|
67
|
+
await new Promise<void>(resolve => setTimeout(resolve, 0));
|
|
68
|
+
|
|
69
|
+
// TouchableOpacity folds its OWN class-derived style into the inner AnimatedView leaf, not
|
|
70
|
+
// the outer Pressable — mirroring React's TouchableOpacity (see adapters/react/src/components/
|
|
71
|
+
// touchable/index.ts's comment: "className is pulled out here, like style, and applied to the
|
|
72
|
+
// inner AnimatedView... it would land on the outer Pressable instead, which is not what a user
|
|
73
|
+
// expects"), so the testID-carrying outer view is NOT where the resolved style lands.
|
|
74
|
+
expect(fabric.find(n => n.props.testID === 'opacity')).toBeDefined();
|
|
75
|
+
const node = fabric.find(n => n.props.backgroundColor === 'red');
|
|
76
|
+
expect(node, 'a committed node received the class-derived style').toBeDefined();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('TouchableHighlight', () => {
|
|
81
|
+
it('resolves a class= on the TouchableHighlight use site onto the real committed view, not the anchor', async () => {
|
|
82
|
+
registerStyles({ card: { backgroundColor: 'red' } });
|
|
83
|
+
|
|
84
|
+
mount(ROOT_TAG, TouchableHighlightHost);
|
|
85
|
+
await new Promise<void>(resolve => setTimeout(resolve, 0));
|
|
86
|
+
|
|
87
|
+
const node = fabric.find(n => n.props.testID === 'highlight');
|
|
88
|
+
expect(node?.props.backgroundColor).toBe('red');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('TouchableWithoutFeedback', () => {
|
|
93
|
+
it('resolves a class= on the TouchableWithoutFeedback use site onto the real committed view, not the anchor', async () => {
|
|
94
|
+
registerStyles({ card: { backgroundColor: 'red' } });
|
|
95
|
+
|
|
96
|
+
mount(ROOT_TAG, TouchableWithoutFeedbackHost);
|
|
97
|
+
await new Promise<void>(resolve => setTimeout(resolve, 0));
|
|
98
|
+
|
|
99
|
+
const node = fabric.find(n => n.props.testID === 'without-feedback');
|
|
100
|
+
expect(node?.props.backgroundColor).toBe('red');
|
|
101
|
+
});
|
|
102
|
+
});
|