@symbiote-native/angular 1.0.0 → 2.0.1

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.
Files changed (248) hide show
  1. package/README.md +13 -10
  2. package/babel-register-composed.cjs +41 -19
  3. package/bin/symbiote-angular-dev.cjs +16 -4
  4. package/build/angular/anchor-host-registry.js +1 -17
  5. package/build/angular/anchor-host-registry.js.map +1 -1
  6. package/build/angular/change-detection-flush.d.ts +31 -0
  7. package/build/angular/change-detection-flush.js +110 -0
  8. package/build/angular/change-detection-flush.js.map +1 -0
  9. package/build/angular/components/activity-indicator-props.d.ts +2 -0
  10. package/build/angular/components/activity-indicator-props.js +2 -0
  11. package/build/angular/components/activity-indicator-props.js.map +1 -0
  12. package/build/angular/components/button-props.d.ts +2 -0
  13. package/build/angular/components/button-props.js +2 -0
  14. package/build/angular/components/button-props.js.map +1 -0
  15. package/build/angular/components/flat-list/index.d.ts +2 -1
  16. package/build/angular/components/flat-list/index.js +22 -10
  17. package/build/angular/components/flat-list/index.js.map +1 -1
  18. package/build/angular/components/image-background-props.d.ts +6 -0
  19. package/build/angular/components/image-background-props.js +2 -0
  20. package/build/angular/components/image-background-props.js.map +1 -0
  21. package/build/angular/components/{image/shared.d.ts → image-shared.d.ts} +1 -1
  22. package/build/angular/components/{image/shared.js → image-shared.js} +7 -2
  23. package/build/angular/components/image-shared.js.map +1 -0
  24. package/build/angular/components/input-accessory-view-props.d.ts +7 -0
  25. package/build/angular/components/input-accessory-view-props.js +9 -0
  26. package/build/angular/components/input-accessory-view-props.js.map +1 -0
  27. package/build/angular/components/keyboard-avoiding-view/index.js +11 -17
  28. package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
  29. package/build/angular/components/modal/index.d.ts +1 -0
  30. package/build/angular/components/modal/index.js +19 -12
  31. package/build/angular/components/modal/index.js.map +1 -1
  32. package/build/angular/components/pressable-props.d.ts +32 -0
  33. package/build/angular/components/pressable-props.js +11 -0
  34. package/build/angular/components/pressable-props.js.map +1 -0
  35. package/build/angular/components/refresh-control-props.d.ts +16 -0
  36. package/build/angular/components/refresh-control-props.js +14 -0
  37. package/build/angular/components/refresh-control-props.js.map +1 -0
  38. package/build/angular/components/safe-area-view-props.d.ts +7 -0
  39. package/build/angular/components/safe-area-view-props.js +11 -0
  40. package/build/angular/components/safe-area-view-props.js.map +1 -0
  41. package/build/angular/components/scroll-view-props.d.ts +76 -0
  42. package/build/angular/components/scroll-view-props.js +18 -0
  43. package/build/angular/components/scroll-view-props.js.map +1 -0
  44. package/build/angular/components/text-input-props.d.ts +45 -0
  45. package/build/angular/components/text-input-props.js +18 -0
  46. package/build/angular/components/text-input-props.js.map +1 -0
  47. package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +6 -0
  48. package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.js +2 -0
  49. package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.js.map +1 -0
  50. package/build/angular/components/touchable-props.d.ts +14 -0
  51. package/build/angular/components/touchable-props.js +13 -0
  52. package/build/angular/components/touchable-props.js.map +1 -0
  53. package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +3 -0
  54. package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.js +2 -0
  55. package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.js.map +1 -0
  56. package/build/angular/components/virtualized-list/index.d.ts +5 -1
  57. package/build/angular/components/virtualized-list/index.js +366 -280
  58. package/build/angular/components/virtualized-list/index.js.map +1 -1
  59. package/build/angular/components.d.ts +20 -26
  60. package/build/angular/components.js +12 -14
  61. package/build/angular/components.js.map +1 -1
  62. package/build/angular/create-portal/index.d.ts +2 -2
  63. package/build/angular/create-portal/index.js +5 -5
  64. package/build/angular/create-tunnel/index.js +1 -1
  65. package/build/angular/element-props.d.ts +53 -0
  66. package/build/angular/element-props.js +2 -0
  67. package/build/angular/element-props.js.map +1 -0
  68. package/build/angular/elements.d.ts +528 -0
  69. package/build/angular/elements.js +1444 -0
  70. package/build/angular/elements.js.map +1 -0
  71. package/build/angular/host-instance/index.js +1 -1
  72. package/build/angular/index.d.ts +4 -2
  73. package/build/angular/index.js +15 -1
  74. package/build/angular/index.js.map +1 -1
  75. package/build/angular/modules/animated/create-animated-component.d.ts +5 -6
  76. package/build/angular/modules/animated/create-animated-component.js +60 -73
  77. package/build/angular/modules/animated/create-animated-component.js.map +1 -1
  78. package/build/angular/modules/animated/index.js +1 -1
  79. package/build/angular/modules/animated/index.js.map +1 -1
  80. package/build/angular/modules/image/index.d.ts +3 -0
  81. package/build/angular/modules/image/index.js +16 -0
  82. package/build/angular/modules/image/index.js.map +1 -0
  83. package/build/angular/primitives/index.d.ts +18 -18
  84. package/build/angular/primitives/index.js +40 -36
  85. package/build/angular/primitives/index.js.map +1 -1
  86. package/build/angular/primitives/shared.d.ts +2 -3
  87. package/build/angular/primitives/shared.js +8 -53
  88. package/build/angular/primitives/shared.js.map +1 -1
  89. package/build/angular/register.d.ts +1 -1
  90. package/build/angular/register.js +12 -31
  91. package/build/angular/register.js.map +1 -1
  92. package/build/angular/render/index.js +3 -3
  93. package/build/angular/render/index.js.map +1 -1
  94. package/build/angular/renderer/index.js +113 -67
  95. package/build/angular/renderer/index.js.map +1 -1
  96. package/build/angular/renderer/value-change.d.ts +2 -0
  97. package/build/angular/renderer/value-change.js +9 -0
  98. package/build/angular/renderer/value-change.js.map +1 -0
  99. package/metro-config.cjs +54 -20
  100. package/metro-css-parser.cjs +2 -1
  101. package/package.json +5 -14
  102. package/src/anchor-host-registry.ts +1 -17
  103. package/src/change-detection-flush.ts +120 -0
  104. package/src/components/activity-indicator-props.ts +21 -0
  105. package/src/components/button-props.ts +26 -0
  106. package/src/components/flat-list/index.ts +12 -4
  107. package/src/components/image-background-props.ts +24 -0
  108. package/src/components/{image/shared.ts → image-shared.ts} +6 -1
  109. package/src/components/input-accessory-view-props.ts +21 -0
  110. package/src/components/keyboard-avoiding-view/index.ts +6 -9
  111. package/src/components/modal/index.ts +15 -7
  112. package/src/components/pressable-props.ts +73 -0
  113. package/src/components/refresh-control-props.ts +43 -0
  114. package/src/components/safe-area-view-props.ts +28 -0
  115. package/src/components/scroll-view-props.ts +109 -0
  116. package/src/components/text-input-props.ts +72 -0
  117. package/src/components/touchable-native-feedback/touchable-native-feedback-props.ts +23 -0
  118. package/src/components/touchable-props.ts +30 -0
  119. package/src/components/touchable-without-feedback/touchable-without-feedback-props.ts +21 -0
  120. package/src/components/virtualized-list/index.ts +239 -156
  121. package/src/components.ts +84 -35
  122. package/src/create-portal/index.ts +5 -5
  123. package/src/create-tunnel/index.ts +1 -1
  124. package/src/diagnostics.ts +1 -1
  125. package/src/element-props.ts +90 -0
  126. package/src/elements.ts +919 -0
  127. package/src/host-instance/index.ts +1 -1
  128. package/src/index.ts +52 -15
  129. package/src/modules/animated/create-animated-component.ts +50 -55
  130. package/src/modules/animated/index.ts +1 -1
  131. package/src/modules/image/index.ts +18 -0
  132. package/src/primitives/index.ts +22 -18
  133. package/src/primitives/shared.ts +11 -44
  134. package/src/register.ts +12 -40
  135. package/src/render/index.ts +3 -3
  136. package/src/renderer/index.ts +122 -73
  137. package/src/renderer/value-change.ts +8 -0
  138. package/babel-lower-host-primitives.cjs +0 -636
  139. package/build/angular/components/activity-indicator/index.android.d.ts +0 -13
  140. package/build/angular/components/activity-indicator/index.android.js +0 -29
  141. package/build/angular/components/activity-indicator/index.android.js.map +0 -1
  142. package/build/angular/components/activity-indicator/index.d.ts +0 -1
  143. package/build/angular/components/activity-indicator/index.ios.d.ts +0 -9
  144. package/build/angular/components/activity-indicator/index.ios.js +0 -26
  145. package/build/angular/components/activity-indicator/index.ios.js.map +0 -1
  146. package/build/angular/components/activity-indicator/index.js +0 -4
  147. package/build/angular/components/activity-indicator/index.js.map +0 -1
  148. package/build/angular/components/activity-indicator/shared.d.ts +0 -67
  149. package/build/angular/components/activity-indicator/shared.js +0 -260
  150. package/build/angular/components/activity-indicator/shared.js.map +0 -1
  151. package/build/angular/components/button.d.ts +0 -68
  152. package/build/angular/components/button.js +0 -360
  153. package/build/angular/components/button.js.map +0 -1
  154. package/build/angular/components/image/index.android.d.ts +0 -15
  155. package/build/angular/components/image/index.android.js +0 -83
  156. package/build/angular/components/image/index.android.js.map +0 -1
  157. package/build/angular/components/image/index.d.ts +0 -1
  158. package/build/angular/components/image/index.ios.d.ts +0 -15
  159. package/build/angular/components/image/index.ios.js +0 -83
  160. package/build/angular/components/image/index.ios.js.map +0 -1
  161. package/build/angular/components/image/index.js +0 -3
  162. package/build/angular/components/image/index.js.map +0 -1
  163. package/build/angular/components/image/shared.js.map +0 -1
  164. package/build/angular/components/image-background.d.ts +0 -85
  165. package/build/angular/components/image-background.js +0 -443
  166. package/build/angular/components/image-background.js.map +0 -1
  167. package/build/angular/components/input-accessory-view/index.d.ts +0 -66
  168. package/build/angular/components/input-accessory-view/index.js +0 -287
  169. package/build/angular/components/input-accessory-view/index.js.map +0 -1
  170. package/build/angular/components/pressable/index.d.ts +0 -134
  171. package/build/angular/components/pressable/index.js +0 -514
  172. package/build/angular/components/pressable/index.js.map +0 -1
  173. package/build/angular/components/refresh-control/index.d.ts +0 -91
  174. package/build/angular/components/refresh-control/index.js +0 -382
  175. package/build/angular/components/refresh-control/index.js.map +0 -1
  176. package/build/angular/components/safe-area-view/index.d.ts +0 -64
  177. package/build/angular/components/safe-area-view/index.js +0 -287
  178. package/build/angular/components/safe-area-view/index.js.map +0 -1
  179. package/build/angular/components/scroll-view/index.android.d.ts +0 -20
  180. package/build/angular/components/scroll-view/index.android.js +0 -262
  181. package/build/angular/components/scroll-view/index.android.js.map +0 -1
  182. package/build/angular/components/scroll-view/index.d.ts +0 -3
  183. package/build/angular/components/scroll-view/index.ios.d.ts +0 -8
  184. package/build/angular/components/scroll-view/index.ios.js +0 -92
  185. package/build/angular/components/scroll-view/index.ios.js.map +0 -1
  186. package/build/angular/components/scroll-view/index.js +0 -6
  187. package/build/angular/components/scroll-view/index.js.map +0 -1
  188. package/build/angular/components/scroll-view/projection.d.ts +0 -67
  189. package/build/angular/components/scroll-view/projection.js +0 -560
  190. package/build/angular/components/scroll-view/projection.js.map +0 -1
  191. package/build/angular/components/scroll-view/shared.d.ts +0 -241
  192. package/build/angular/components/scroll-view/shared.js +0 -848
  193. package/build/angular/components/scroll-view/shared.js.map +0 -1
  194. package/build/angular/components/scroll-view/sticky-header.d.ts +0 -40
  195. package/build/angular/components/scroll-view/sticky-header.js +0 -224
  196. package/build/angular/components/scroll-view/sticky-header.js.map +0 -1
  197. package/build/angular/components/switch/index.android.d.ts +0 -24
  198. package/build/angular/components/switch/index.android.js +0 -112
  199. package/build/angular/components/switch/index.android.js.map +0 -1
  200. package/build/angular/components/switch/index.d.ts +0 -1
  201. package/build/angular/components/switch/index.ios.d.ts +0 -23
  202. package/build/angular/components/switch/index.ios.js +0 -111
  203. package/build/angular/components/switch/index.ios.js.map +0 -1
  204. package/build/angular/components/switch/index.js +0 -4
  205. package/build/angular/components/switch/index.js.map +0 -1
  206. package/build/angular/components/switch/shared.d.ts +0 -49
  207. package/build/angular/components/switch/shared.js +0 -191
  208. package/build/angular/components/switch/shared.js.map +0 -1
  209. package/build/angular/components/text-input.d.ts +0 -167
  210. package/build/angular/components/text-input.js +0 -684
  211. package/build/angular/components/text-input.js.map +0 -1
  212. package/build/angular/components/touchable/index.d.ts +0 -283
  213. package/build/angular/components/touchable/index.js +0 -1453
  214. package/build/angular/components/touchable/index.js.map +0 -1
  215. package/build/angular/components/touchable-native-feedback/index.d.ts +0 -87
  216. package/build/angular/components/touchable-native-feedback/index.js +0 -409
  217. package/build/angular/components/touchable-native-feedback/index.js.map +0 -1
  218. package/build/angular/state-style.d.ts +0 -9
  219. package/build/angular/state-style.js +0 -39
  220. package/build/angular/state-style.js.map +0 -1
  221. package/metro-transformer.cjs +0 -69
  222. package/src/components/activity-indicator/index.android.ts +0 -23
  223. package/src/components/activity-indicator/index.ios.ts +0 -21
  224. package/src/components/activity-indicator/index.ts +0 -4
  225. package/src/components/activity-indicator/shared.ts +0 -225
  226. package/src/components/button.ts +0 -237
  227. package/src/components/image/index.android.ts +0 -95
  228. package/src/components/image/index.ios.ts +0 -95
  229. package/src/components/image/index.ts +0 -3
  230. package/src/components/image-background.ts +0 -308
  231. package/src/components/input-accessory-view/index.ts +0 -246
  232. package/src/components/pressable/index.ts +0 -522
  233. package/src/components/refresh-control/index.ts +0 -349
  234. package/src/components/safe-area-view/index.ts +0 -247
  235. package/src/components/scroll-view/index.android.ts +0 -205
  236. package/src/components/scroll-view/index.ios.ts +0 -81
  237. package/src/components/scroll-view/index.ts +0 -7
  238. package/src/components/scroll-view/projection.ts +0 -713
  239. package/src/components/scroll-view/shared.ts +0 -1093
  240. package/src/components/scroll-view/sticky-header.ts +0 -267
  241. package/src/components/switch/index.android.ts +0 -113
  242. package/src/components/switch/index.ios.ts +0 -112
  243. package/src/components/switch/index.ts +0 -4
  244. package/src/components/switch/shared.ts +0 -284
  245. package/src/components/text-input.ts +0 -669
  246. package/src/components/touchable/index.ts +0 -956
  247. package/src/components/touchable-native-feedback/index.ts +0 -327
  248. package/src/state-style.ts +0 -39
@@ -1,69 +0,0 @@
1
- // The Angular app-side Metro transformer: host-primitive lowering + the CSS pipeline.
2
- //
3
- // Point `metro.config.js`'s `babelTransformerPath` here INSTEAD of `./metro-css-parser`, and do
4
- // NOT also list `./babel-lower-host-primitives` in `babel.config.js` — as a babel plugin it does
5
- // half the job, silently.
6
- //
7
- // WHY a source pre-pass and not a plugin. Angular's linker reads an INLINE template by SLICING THE
8
- // FILE'S SOURCE TEXT at the AST node's own byte range (`templateFromPartialCode` in
9
- // `@angular/compiler-cli`'s bundled linker: `code: this.code`, `range: {startPos, endPos}`), never
10
- // from the string the AST carries. So a plugin that rewrites `template` in the AST is invisible to
11
- // a linker running in the SAME babel pass, while its edit to `dependencies` — read as an ordinary
12
- // AST array — lands. The result is the worst of both: the primitives are gone from `dependencies`
13
- // and the tags are still `<View>`/`<Pressable>`, so they match no directive at all, no component
14
- // template runs, and the screen loses its styles and its press handlers with nothing red anywhere.
15
- //
16
- // Printing the lowered AST back to TEXT before Metro parses it is what makes the two agree: the
17
- // linker then slices the rewritten template out of the source it was handed.
18
- //
19
- // .cjs for the same reason as this package's other loose scripts: Metro `require()`s a
20
- // babelTransformerPath directly, and the package is "type": "module".
21
- const { transformSync } = require('@babel/core');
22
- const { readFileSync } = require('node:fs');
23
- const { createHash } = require('node:crypto');
24
- const {
25
- createCssMetroTransformer,
26
- resolveUpstreamTransformer,
27
- } = require('@symbiote-native/css-parser');
28
-
29
- const LOWER_PLUGIN_PATH = require.resolve('./babel-lower-host-primitives.cjs');
30
- const lowerHostPrimitives = require(LOWER_PLUGIN_PATH);
31
-
32
- // ngc's partial output is the only thing this can act on, and every such file names the declaration
33
- // helper. Cheaper than parsing every file in the bundle to find out it has no component in it.
34
- const PARTIAL_DECLARATION_MARKER = 'ɵɵngDeclareComponent';
35
-
36
- function createLoweringTransformer(upstreamTransformer) {
37
- return {
38
- transform(params) {
39
- if (!params.src.includes(PARTIAL_DECLARATION_MARKER)) {
40
- return upstreamTransformer.transform(params);
41
- }
42
- const lowered = transformSync(params.src, {
43
- filename: params.filename,
44
- babelrc: false,
45
- configFile: false,
46
- plugins: [lowerHostPrimitives],
47
- });
48
- return upstreamTransformer.transform({
49
- ...params,
50
- src: lowered?.code ?? params.src,
51
- });
52
- },
53
- // Metro's own key covers the upstream transformer and babel.config.js, NOT a plugin this file
54
- // require()s itself — so editing the lowering rules would otherwise be served from cache and
55
- // read on device as "the change did nothing".
56
- getCacheKey(...args) {
57
- const upstream = upstreamTransformer.getCacheKey?.(...args) ?? '';
58
- const plugin = createHash('sha1')
59
- .update(readFileSync(LOWER_PLUGIN_PATH))
60
- .digest('hex');
61
- return `${upstream}-symbiote-lower-${plugin}`;
62
- },
63
- };
64
- }
65
-
66
- module.exports = createCssMetroTransformer(
67
- createLoweringTransformer(resolveUpstreamTransformer()),
68
- );
69
- module.exports.createLoweringTransformer = createLoweringTransformer;
@@ -1,23 +0,0 @@
1
- import { ChangeDetectionStrategy, Component } from '@angular/core';
2
- import { DescriptorOutlet } from '../../descriptor-to-angular';
3
- import { ActivityIndicatorBase } from './shared';
4
- import { SymbioteStyleInputDirective } from '../../primitives';
5
- export type { IActivityIndicatorProps } from './shared';
6
-
7
- @Component({
8
- selector: 'ActivityIndicator',
9
- standalone: true,
10
- hostDirectives: [
11
- { directive: SymbioteStyleInputDirective, inputs: ['style'] },
12
- ],
13
- imports: [DescriptorOutlet],
14
- changeDetection: ChangeDetectionStrategy.OnPush,
15
- template: `<symbiote-descriptor-outlet [node]="descriptor" />`,
16
- })
17
- export class ActivityIndicator extends ActivityIndicatorBase {
18
- protected readonly defaultColor = null;
19
- protected override readonly nativeExtras = {
20
- styleAttr: 'Normal',
21
- indeterminate: true,
22
- };
23
- }
@@ -1,21 +0,0 @@
1
- import { ChangeDetectionStrategy, Component } from '@angular/core';
2
- import { DescriptorOutlet } from '../../descriptor-to-angular';
3
- import { ActivityIndicatorBase } from './shared';
4
- import { SymbioteStyleInputDirective } from '../../primitives';
5
- export type { IActivityIndicatorProps } from './shared';
6
-
7
- const IOS_DEFAULT_COLOR = '#999999';
8
-
9
- @Component({
10
- selector: 'ActivityIndicator',
11
- standalone: true,
12
- hostDirectives: [
13
- { directive: SymbioteStyleInputDirective, inputs: ['style'] },
14
- ],
15
- imports: [DescriptorOutlet],
16
- changeDetection: ChangeDetectionStrategy.OnPush,
17
- template: `<symbiote-descriptor-outlet [node]="descriptor" />`,
18
- })
19
- export class ActivityIndicator extends ActivityIndicatorBase {
20
- protected readonly defaultColor = IOS_DEFAULT_COLOR;
21
- }
@@ -1,4 +0,0 @@
1
- // Base/default ActivityIndicator. Re-exports the iOS build; Metro picks index.ios.ts /
2
- // index.android.ts in platform bundles.
3
-
4
- export * from './index.ios';
@@ -1,225 +0,0 @@
1
- import {
2
- Directive,
3
- ElementRef,
4
- EventEmitter,
5
- inject,
6
- Input,
7
- Output,
8
- } from '@angular/core';
9
- import {
10
- renderActivityIndicator,
11
- resolveAccessibilityProps,
12
- type IAccessibilityProps,
13
- type IAccessibilityStateValue,
14
- type IActivityIndicatorPlatform,
15
- type IActivityIndicatorProps,
16
- type IActivityIndicatorSize,
17
- type IAriaProps,
18
- } from '@symbiote-native/components';
19
- import type { ISymbioteEvent } from '@symbiote-native/engine';
20
- import type { IDescriptor } from '@symbiote-native/components';
21
- import { anchorHostStyle } from '../../primitives';
22
-
23
- export type {
24
- IActivityIndicatorProps,
25
- IActivityIndicatorSize,
26
- } from '@symbiote-native/components';
27
-
28
- // Narrows anchorHostStyle's `unknown` (it reads an opaque engine prop bag) to the shape
29
- // IActivityIndicatorProps['style'] actually declares, the same runtime guard image/shared.ts's
30
- // asStyle() uses for the identical reason — a style value is structurally opaque at the type
31
- // level, so this only rules out non-objects, never validates individual style keys.
32
- function asStyle(value: unknown): IActivityIndicatorProps['style'] {
33
- return typeof value === 'object' && value !== null ? value : undefined;
34
- }
35
-
36
- // What the component itself takes as plain @Input()s: the full shared, cross-adapter
37
- // IActivityIndicatorProps surface minus onLayout and the accessibility callbacks, which it
38
- // exposes as real @Output() EventEmitters instead (see the class below), mirroring Pressable's
39
- // IAngularPressableInputs split.
40
- export type IActivityIndicatorInputs = Omit<
41
- IActivityIndicatorProps,
42
- | 'onLayout'
43
- | 'onAccessibilityAction'
44
- | 'onAccessibilityTap'
45
- | 'onMagicTap'
46
- | 'onAccessibilityEscape'
47
- >;
48
-
49
- @Directive()
50
- export abstract class ActivityIndicatorBase implements IActivityIndicatorInputs {
51
- @Input() animating?: boolean;
52
- @Input() color?: string;
53
- @Input() hidesWhenStopped?: boolean;
54
- @Input() nativeID?: string;
55
- @Input() size?: IActivityIndicatorSize;
56
- @Input() style?: IActivityIndicatorProps['style'];
57
- @Input() testID?: string;
58
- // Real @Output()s. This component renders through DescriptorOutlet (`symbiote-descriptor-
59
- // outlet`), not a hand-written template: emitterHandler() below wraps each EventEmitter into a
60
- // plain callback under the SAME onX key the shared, cross-adapter IActivityIndicatorProps
61
- // expects, so the Descriptor's props bag still carries a function the engine's routeProp
62
- // recognizes and routes to setEventListener — the outlet's renderer.setProperty call never
63
- // sees an EventEmitter, only the wrapper.
64
- @Output() readonly layout = new EventEmitter<ISymbioteEvent>();
65
-
66
- @Input() accessible?: boolean;
67
- @Input() accessibilityLabel?: string;
68
- @Input() accessibilityHint?: string;
69
- @Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
70
- @Input() accessibilityState?: IAccessibilityStateValue;
71
- @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
72
- @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
73
- @Input() accessibilityLabelledBy?: string | string[];
74
- @Input()
75
- importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
76
- @Input()
77
- accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
78
- @Input() screenReaderFocusable?: boolean;
79
- @Input() accessibilityViewIsModal?: boolean;
80
- @Input() accessibilityElementsHidden?: boolean;
81
- @Input() accessibilityIgnoresInvertColors?: boolean;
82
- @Input() accessibilityLanguage?: string;
83
- @Input() accessibilityRespondsToUserInteraction?: boolean;
84
- @Input() accessibilityShowsLargeContentViewer?: boolean;
85
- @Input() accessibilityLargeContentTitle?: string;
86
- @Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
87
- @Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
88
- @Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
89
- @Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
90
-
91
- @Input() role?: IAriaProps['role'];
92
- @Input('aria-label') ariaLabel?: string;
93
- @Input('aria-labelledby') ariaLabelledBy?: string;
94
- @Input('aria-live') ariaLive?: IAriaProps['aria-live'];
95
- @Input('aria-hidden') ariaHidden?: boolean;
96
- @Input('aria-busy') ariaBusy?: boolean;
97
- @Input('aria-checked') ariaChecked?: boolean | 'mixed';
98
- @Input('aria-disabled') ariaDisabled?: boolean;
99
- @Input('aria-expanded') ariaExpanded?: boolean;
100
- @Input('aria-selected') ariaSelected?: boolean;
101
- @Input('aria-modal') ariaModal?: boolean;
102
- @Input('aria-valuemax') ariaValueMax?: number;
103
- @Input('aria-valuemin') ariaValueMin?: number;
104
- @Input('aria-valuenow') ariaValueNow?: number;
105
- @Input('aria-valuetext') ariaValueText?: string;
106
-
107
- protected abstract readonly defaultColor: string | null;
108
- protected readonly nativeExtras: Readonly<Record<string, unknown>> = {};
109
-
110
- // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
111
- // onto (see anchorHostStyle's doc comment) — NOT the descriptor-outlet-rendered wrapper the
112
- // `descriptor` getter below builds. Merged FIRST so an explicit `style` @Input still wins
113
- // (flattenStyle's later-wins collapse), mirroring every other composed component's anchor merge.
114
- private readonly elementRef = inject(ElementRef);
115
-
116
- // Stable bound wrappers (created ONCE, not per `descriptor` access) fed to emitterHandler below.
117
- // jsonEqual (core/engine/src/commit.ts) falls through to Object.is for a function leaf, so a
118
- // fresh closure built inside the `descriptor` getter would never equal the previous frame's
119
- // closure even when nothing changed — every CD pass would read as "props changed" and force a
120
- // real Fabric re-clone cascading up every ancestor to the root (the same hazard
121
- // AnimatedComponentBase.reconcile() and ScrollViewStickyHeader's onHostLayout guard against).
122
- private readonly onLayoutHandler = (event: ISymbioteEvent): void =>
123
- this.layout.emit(event);
124
- private readonly onAccessibilityActionHandler = (
125
- event: ISymbioteEvent,
126
- ): void => this.accessibilityAction.emit(event);
127
- private readonly onAccessibilityTapHandler = (event: ISymbioteEvent): void =>
128
- this.accessibilityTap.emit(event);
129
- private readonly onMagicTapHandler = (event: ISymbioteEvent): void =>
130
- this.magicTap.emit(event);
131
- private readonly onAccessibilityEscapeHandler = (
132
- event: ISymbioteEvent,
133
- ): void => this.accessibilityEscape.emit(event);
134
-
135
- get descriptor(): IDescriptor {
136
- const props = resolveAccessibilityProps<IActivityIndicatorProps>({
137
- animating: this.animating,
138
- color: this.color,
139
- hidesWhenStopped: this.hidesWhenStopped,
140
- nativeID: this.nativeID,
141
- size: this.size,
142
- style: [asStyle(anchorHostStyle(this.elementRef)), this.style],
143
- testID: this.testID,
144
- onLayout: this.emitterHandler(this.layout, this.onLayoutHandler),
145
- accessible: this.accessible,
146
- accessibilityLabel: this.accessibilityLabel,
147
- accessibilityHint: this.accessibilityHint,
148
- accessibilityRole: this.accessibilityRole,
149
- accessibilityState: this.accessibilityState,
150
- accessibilityValue: this.accessibilityValue,
151
- accessibilityActions: this.accessibilityActions,
152
- accessibilityLabelledBy: this.accessibilityLabelledBy,
153
- importantForAccessibility: this.importantForAccessibility,
154
- accessibilityLiveRegion: this.accessibilityLiveRegion,
155
- screenReaderFocusable: this.screenReaderFocusable,
156
- accessibilityViewIsModal: this.accessibilityViewIsModal,
157
- accessibilityElementsHidden: this.accessibilityElementsHidden,
158
- accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
159
- accessibilityLanguage: this.accessibilityLanguage,
160
- accessibilityRespondsToUserInteraction:
161
- this.accessibilityRespondsToUserInteraction,
162
- accessibilityShowsLargeContentViewer:
163
- this.accessibilityShowsLargeContentViewer,
164
- accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
165
- onAccessibilityAction: this.emitterHandler(
166
- this.accessibilityAction,
167
- this.onAccessibilityActionHandler,
168
- ),
169
- onAccessibilityTap: this.emitterHandler(
170
- this.accessibilityTap,
171
- this.onAccessibilityTapHandler,
172
- ),
173
- onMagicTap: this.emitterHandler(this.magicTap, this.onMagicTapHandler),
174
- onAccessibilityEscape: this.emitterHandler(
175
- this.accessibilityEscape,
176
- this.onAccessibilityEscapeHandler,
177
- ),
178
- role: this.role,
179
- 'aria-label': this.ariaLabel,
180
- 'aria-labelledby': this.ariaLabelledBy,
181
- 'aria-live': this.ariaLive,
182
- 'aria-hidden': this.ariaHidden,
183
- 'aria-busy': this.ariaBusy,
184
- 'aria-checked': this.ariaChecked,
185
- 'aria-disabled': this.ariaDisabled,
186
- 'aria-expanded': this.ariaExpanded,
187
- 'aria-selected': this.ariaSelected,
188
- 'aria-modal': this.ariaModal,
189
- 'aria-valuemax': this.ariaValueMax,
190
- 'aria-valuemin': this.ariaValueMin,
191
- 'aria-valuenow': this.ariaValueNow,
192
- 'aria-valuetext': this.ariaValueText,
193
- });
194
-
195
- const { animating, color, hidesWhenStopped, size, style, ...passthrough } =
196
- props;
197
- return renderActivityIndicator(
198
- {
199
- animating: animating !== false,
200
- color,
201
- hidesWhenStopped: hidesWhenStopped !== false,
202
- size: size ?? 'small',
203
- style,
204
- passthrough,
205
- },
206
- this.platform,
207
- );
208
- }
209
-
210
- private get platform(): IActivityIndicatorPlatform {
211
- return { defaultColor: this.defaultColor, nativeExtras: this.nativeExtras };
212
- }
213
-
214
- // Gates a STABLE bound handler behind `observed`, so an unbound event still resolves to
215
- // `undefined` in the descriptor's props bag — the same "undefined means nobody cares" contract
216
- // the old @Input() callback had, letting resolveAccessibilityProps drop the key entirely instead
217
- // of handing the engine a no-op function. `handler` must be one of the readonly bound fields
218
- // above, never a closure built here — see their doc comment for why.
219
- private emitterHandler(
220
- emitter: EventEmitter<ISymbioteEvent>,
221
- handler: (event: ISymbioteEvent) => void,
222
- ): ((event: ISymbioteEvent) => void) | undefined {
223
- return emitter.observed ? handler : undefined;
224
- }
225
- }
@@ -1,237 +0,0 @@
1
- // Button for Angular. The minimal cross-platform button in RN's iOS shape (Button.js): a
2
- // TouchableOpacity wrapping a Text. The base text style, the role constant, and the color fold are
3
- // shared in @symbiote-native/components/view; Angular only composes its TouchableOpacity + a
4
- // symbiote-text child and re-maps the few Button-owned props. No JS-side platform branch, so this
5
- // stays a flat single file.
6
- //
7
- // RN's Button fixes accessibilityRole="button", marks the root accessible, and propagates
8
- // `disabled` into the accessibility state; those three win over any caller value. `title` becomes
9
- // the Text child; disabled forwards straight; touchSoundDisabled maps to the pressable's
10
- // android_disableSound. Every other field of the shared IButtonProps stays RE-EXPORTED from
11
- // @symbiote-native/components verbatim. onPress and the four accessibility callbacks are the
12
- // exceptions: each is a real @Output() here (`press`, `accessibilityAction`, `accessibilityTap`,
13
- // `magicTap`, `accessibilityEscape`), mirroring the Vue adapter's Button, which forks the same
14
- // onPress field the same way — not a new precedent, the existing one extended to accessibility.
15
-
16
- import {
17
- CUSTOM_ELEMENTS_SCHEMA,
18
- ChangeDetectionStrategy,
19
- Component,
20
- ElementRef,
21
- EventEmitter,
22
- inject,
23
- Input,
24
- Output,
25
- signal,
26
- type DoCheck,
27
- } from '@angular/core';
28
- import {
29
- BUTTON_ACCESSIBILITY_ROLE,
30
- resolveButtonTextStyle,
31
- type IAccessibilityProps,
32
- type IAccessibilityStateValue,
33
- type IAriaProps,
34
- type IButtonProps as ICoreButtonProps,
35
- } from '@symbiote-native/components';
36
- import type {
37
- ISymbioteEvent,
38
- ITextStyle,
39
- IStyleProp,
40
- IViewStyle,
41
- } from '@symbiote-native/engine';
42
- import { anchorStyleProp, TextHost } from '../primitives';
43
- import { TouchableOpacity } from './touchable';
44
- import {
45
- gateWanted,
46
- injectGateDemandAbove,
47
- provideGateDemand,
48
- type IGateDemand,
49
- type IGatedAccessibilityEvent,
50
- } from '../gate-demand';
51
-
52
- export type IButtonProps = Omit<
53
- ICoreButtonProps,
54
- | 'onPress'
55
- | 'onAccessibilityAction'
56
- | 'onAccessibilityTap'
57
- | 'onMagicTap'
58
- | 'onAccessibilityEscape'
59
- >;
60
-
61
- @Component({
62
- selector: 'Button',
63
- standalone: true,
64
- viewProviders: [provideGateDemand(() => Button)],
65
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
66
- imports: [TouchableOpacity, TextHost],
67
- changeDetection: ChangeDetectionStrategy.OnPush,
68
- template: `
69
- <TouchableOpacity
70
- [style]="anchorStyle"
71
- (press)="press.emit($event)"
72
- [disabled]="disabled"
73
- [android_disableSound]="touchSoundDisabled"
74
- [accessibilityRole]="buttonRole"
75
- [accessible]="true"
76
- [accessibilityState]="{ disabled }"
77
- [testID]="testID"
78
- [nativeID]="nativeID"
79
- [hasTVPreferredFocus]="hasTVPreferredFocus"
80
- [nextFocusDown]="nextFocusDown"
81
- [nextFocusForward]="nextFocusForward"
82
- [nextFocusLeft]="nextFocusLeft"
83
- [nextFocusRight]="nextFocusRight"
84
- [nextFocusUp]="nextFocusUp"
85
- [accessibilityLabel]="accessibilityLabel"
86
- [accessibilityHint]="accessibilityHint"
87
- [accessibilityValue]="accessibilityValue"
88
- [accessibilityActions]="accessibilityActions"
89
- [accessibilityLabelledBy]="accessibilityLabelledBy"
90
- [importantForAccessibility]="importantForAccessibility"
91
- [accessibilityLiveRegion]="accessibilityLiveRegion"
92
- [screenReaderFocusable]="screenReaderFocusable"
93
- [accessibilityViewIsModal]="accessibilityViewIsModal"
94
- [accessibilityElementsHidden]="accessibilityElementsHidden"
95
- [accessibilityIgnoresInvertColors]="accessibilityIgnoresInvertColors"
96
- [accessibilityLanguage]="accessibilityLanguage"
97
- [accessibilityRespondsToUserInteraction]="
98
- accessibilityRespondsToUserInteraction
99
- "
100
- [accessibilityShowsLargeContentViewer]="
101
- accessibilityShowsLargeContentViewer
102
- "
103
- [accessibilityLargeContentTitle]="accessibilityLargeContentTitle"
104
- (accessibilityAction)="accessibilityAction.emit($event)"
105
- (accessibilityTap)="accessibilityTap.emit($event)"
106
- (magicTap)="magicTap.emit($event)"
107
- (accessibilityEscape)="accessibilityEscape.emit($event)"
108
- [ariaLabel]="ariaLabel"
109
- [ariaBusy]="ariaBusy"
110
- [ariaChecked]="ariaChecked"
111
- [ariaDisabled]="ariaDisabled"
112
- [ariaExpanded]="ariaExpanded"
113
- [ariaHidden]="ariaHidden"
114
- [ariaLabelledBy]="ariaLabelledBy"
115
- [ariaLive]="ariaLive"
116
- [ariaSelected]="ariaSelected"
117
- [ariaModal]="ariaModal"
118
- [ariaValueMax]="ariaValueMax"
119
- [ariaValueMin]="ariaValueMin"
120
- [ariaValueNow]="ariaValueNow"
121
- [ariaValueText]="ariaValueText"
122
- [role]="role"
123
- >
124
- <symbiote-text [style]="textStyle">{{ title }}</symbiote-text>
125
- </TouchableOpacity>
126
- `,
127
- })
128
- export class Button implements IButtonProps, DoCheck {
129
- // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
130
- // onto (see anchorHostStyle's doc comment in primitives/shared.ts) — NOT the inner
131
- // TouchableOpacity/Pressable one level down. RN's real Button takes no `style` prop, so this
132
- // is the only style source forwarded.
133
- private readonly elementRef = inject(ElementRef);
134
-
135
- @Output() readonly press = new EventEmitter<ISymbioteEvent>();
136
- @Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
137
- @Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
138
- @Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
139
- @Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
140
-
141
- // This wrapper binds the four gated accessibility events on the component it renders, which
142
- // Angular forces to be unconditional and which would light that component's gates on every
143
- // instance. It answers for them instead — see `gate-demand.ts`.
144
- private readonly gateDemandAbove = injectGateDemandAbove();
145
-
146
- wantsGate(name: IGatedAccessibilityEvent): boolean {
147
- return gateWanted(this.gateDemandAbove, name, this[name]);
148
- }
149
-
150
- // Button-owned props: title is the Text child, color/disabled fold into the label style, and
151
- // touchSoundDisabled re-maps onto TouchableOpacity.
152
- @Input() title = '';
153
- @Input() color?: string;
154
- @Input() disabled?: boolean;
155
- @Input() touchSoundDisabled?: boolean;
156
- @Input() testID?: string;
157
-
158
- // TV-focus props (Button.js): inert on a phone host, forwarded through TouchableOpacity.
159
- @Input() hasTVPreferredFocus?: boolean;
160
- @Input() nextFocusDown?: number;
161
- @Input() nextFocusForward?: number;
162
- @Input() nextFocusLeft?: number;
163
- @Input() nextFocusRight?: number;
164
- @Input() nextFocusUp?: number;
165
-
166
- // Accessibility surface (IAccessibilityProps). accessibilityRole, accessible, and
167
- // accessibilityState are declared for surface completeness but Button forces its own
168
- // (button / true / { disabled }); the caller value is ignored, mirroring RN's Button.js.
169
- @Input() nativeID?: string;
170
- @Input() accessible?: boolean;
171
- @Input() accessibilityLabel?: string;
172
- @Input() accessibilityHint?: string;
173
- @Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
174
- @Input() accessibilityState?: IAccessibilityStateValue;
175
- @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
176
- @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
177
- @Input() accessibilityLabelledBy?: string | string[];
178
- @Input()
179
- importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
180
- @Input()
181
- accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
182
- @Input() screenReaderFocusable?: boolean;
183
- @Input() accessibilityViewIsModal?: boolean;
184
- @Input() accessibilityElementsHidden?: boolean;
185
- @Input() accessibilityIgnoresInvertColors?: boolean;
186
- @Input() accessibilityLanguage?: string;
187
- @Input() accessibilityRespondsToUserInteraction?: boolean;
188
- @Input() accessibilityShowsLargeContentViewer?: boolean;
189
- @Input() accessibilityLargeContentTitle?: string;
190
-
191
- // Web-alias a11y surface (IAriaProps). External dashed aliases are exposed as Angular inputs and
192
- // forwarded to TouchableOpacity's camelCase aria inputs.
193
- @Input() role?: IAriaProps['role'];
194
- @Input('aria-label') ariaLabel?: string;
195
- @Input('aria-labelledby') ariaLabelledBy?: string;
196
- @Input('aria-live') ariaLive?: IAriaProps['aria-live'];
197
- @Input('aria-hidden') ariaHidden?: boolean;
198
- @Input('aria-busy') ariaBusy?: boolean;
199
- @Input('aria-checked') ariaChecked?: boolean | 'mixed';
200
- @Input('aria-disabled') ariaDisabled?: boolean;
201
- @Input('aria-expanded') ariaExpanded?: boolean;
202
- @Input('aria-selected') ariaSelected?: boolean;
203
- @Input('aria-modal') ariaModal?: boolean;
204
- @Input('aria-valuemax') ariaValueMax?: number;
205
- @Input('aria-valuemin') ariaValueMin?: number;
206
- @Input('aria-valuenow') ariaValueNow?: number;
207
- @Input('aria-valuetext') ariaValueText?: string;
208
-
209
- // RN's Button is always accessibilityRole="button"; the shared role constant, not a literal.
210
- readonly buttonRole = BUTTON_ACCESSIBILITY_ROLE;
211
-
212
- // The label style with the caller color tinted in and `disabled` greying it out (disabled wins),
213
- // computed by the shared fold so every adapter paints the identical button.
214
- get textStyle(): ITextStyle {
215
- return resolveButtonTextStyle(this.color, this.disabled);
216
- }
217
-
218
- // Polled, not read live: a class toggled after mount reaches the anchor through
219
- // addClass/removeClass, which dirties nothing, so a plain getter froze at its creation value.
220
- // Button cannot use SymbioteStyleInputDirective instead - RN's Button has no `style` prop, so
221
- // there is no `style` @Input for it to hang off.
222
- //
223
- // ngDoCheck runs during the PARENT's refresh even when this view is skipped; the signal write is
224
- // what marks this view. The anchor returns the same props.style reference until a commit changes
225
- // it, so Object.is makes an unchanged poll free.
226
- private readonly anchorStyleValue = signal<
227
- IStyleProp<IViewStyle> | undefined
228
- >(undefined);
229
-
230
- ngDoCheck(): void {
231
- this.anchorStyleValue.set(anchorStyleProp<IViewStyle>(this.elementRef));
232
- }
233
-
234
- get anchorStyle(): IStyleProp<IViewStyle> | undefined {
235
- return this.anchorStyleValue();
236
- }
237
- }
@@ -1,95 +0,0 @@
1
- import {
2
- CUSTOM_ELEMENTS_SCHEMA,
3
- Component,
4
- ElementRef,
5
- inject,
6
- signal,
7
- type DoCheck,
8
- type OnChanges,
9
- } from '@angular/core';
10
- import {
11
- anchorHostStyle,
12
- ImageHost,
13
- SymbioteHostPropsDirective,
14
- SymbioteStyleInputDirective,
15
- } from '../../primitives';
16
- import {
17
- IMAGE_INPUTS,
18
- IMAGE_OUTPUTS,
19
- ImageBase,
20
- resolveImageProps,
21
- } from './shared';
22
- export { setImageSourceResolver } from './shared';
23
- export type {
24
- IImageProps,
25
- IImageSource,
26
- IImageSourceProp,
27
- IResizeMode,
28
- IImageSize,
29
- IImageCacheStatus,
30
- } from './shared';
31
-
32
- @Component({
33
- selector: 'Image',
34
- standalone: true,
35
- hostDirectives: [
36
- { directive: SymbioteStyleInputDirective, inputs: ['style'] },
37
- ],
38
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
39
- imports: [ImageHost, SymbioteHostPropsDirective],
40
- inputs: IMAGE_INPUTS,
41
- outputs: IMAGE_OUTPUTS,
42
- template: `
43
- <symbiote-image
44
- [symbioteHostProps]="imageProps()"
45
- (loadStart)="handleLoadStart($event)"
46
- (load)="handleLoad($event)"
47
- (loadEnd)="handleLoadEnd($event)"
48
- (error)="handleError($event)"
49
- (progress)="handleProgress($event)"
50
- (partialLoad)="handlePartialLoad($event)"
51
- />
52
- `,
53
- })
54
- export class Image extends ImageBase implements OnChanges, DoCheck {
55
- // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
56
- // onto (see anchorHostStyle's doc comment) — NOT the inner `symbiote-image` one level down.
57
- private readonly elementRef = inject(ElementRef);
58
-
59
- // The anchor's class-derived style is written by the renderer's addClass/removeClass and never
60
- // reaches Angular's input pipeline (a bare `class="x"` never appears in SimpleChanges — see
61
- // anchorHostStyle's doc comment), so ImageBase's inputsRevision cannot see it. Hence its own
62
- // signal: a plain field read inside a computed() would be untracked and the bag would go stale
63
- // the moment a `[class.x]`/`[ngClass]` toggled.
64
- //
65
- // ngDoCheck is the right cadence: render3's callHooks flushes a node's pre-order hooks at the
66
- // next `ɵɵadvance` past it (or in refreshView's post-template flush), i.e. AFTER the declaring
67
- // template's ɵɵclassProp wrote the class onto this element and BEFORE this component's own view
68
- // refreshes — the exact window a class poll needs. callHooks also runs under
69
- // setActiveConsumer(null), so the write registers no dependency on the caller's view (no NG0600).
70
- // commitClassStyle allocates a fresh style array only when a token actually moved, so signal.set's
71
- // own Object.is check makes an unchanged poll a no-op that dirties nothing.
72
- //
73
- // Known gap, shared with every other component polling this way (Pressable, SafeAreaView,
74
- // TouchableNativeFeedback): `[ngClass]` applies its tokens from NgClass's OWN ngDoCheck, and a
75
- // node's hooks flush in registration order with the component's first, so an [ngClass] flip lands
76
- // one pass after this poll reads it. `class=` and `[class.x]` are written by the declaring
77
- // template's styling instructions and so are always current here.
78
- private readonly anchorStyle = signal<unknown>(undefined);
79
-
80
- // ImageBase is undecorated, so the input bump is declared here rather than inherited.
81
- ngOnChanges(): void {
82
- this.bumpInputsRevision();
83
- }
84
-
85
- ngDoCheck(): void {
86
- this.anchorStyle.set(anchorHostStyle(this.elementRef));
87
- }
88
-
89
- protected override buildImageProps(): Record<string, unknown> {
90
- return resolveImageProps({
91
- ...this.imageInputProps,
92
- style: [this.anchorStyle(), this.style],
93
- });
94
- }
95
- }