@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.
- package/README.md +13 -10
- package/babel-register-composed.cjs +41 -19
- package/bin/symbiote-angular-dev.cjs +16 -4
- package/build/angular/anchor-host-registry.js +1 -17
- package/build/angular/anchor-host-registry.js.map +1 -1
- package/build/angular/change-detection-flush.d.ts +31 -0
- package/build/angular/change-detection-flush.js +110 -0
- package/build/angular/change-detection-flush.js.map +1 -0
- package/build/angular/components/activity-indicator-props.d.ts +2 -0
- package/build/angular/components/activity-indicator-props.js +2 -0
- package/build/angular/components/activity-indicator-props.js.map +1 -0
- package/build/angular/components/button-props.d.ts +2 -0
- package/build/angular/components/button-props.js +2 -0
- package/build/angular/components/button-props.js.map +1 -0
- package/build/angular/components/flat-list/index.d.ts +2 -1
- package/build/angular/components/flat-list/index.js +22 -10
- package/build/angular/components/flat-list/index.js.map +1 -1
- package/build/angular/components/image-background-props.d.ts +6 -0
- package/build/angular/components/image-background-props.js +2 -0
- package/build/angular/components/image-background-props.js.map +1 -0
- package/build/angular/components/{image/shared.d.ts → image-shared.d.ts} +1 -1
- package/build/angular/components/{image/shared.js → image-shared.js} +7 -2
- package/build/angular/components/image-shared.js.map +1 -0
- package/build/angular/components/input-accessory-view-props.d.ts +7 -0
- package/build/angular/components/input-accessory-view-props.js +9 -0
- package/build/angular/components/input-accessory-view-props.js.map +1 -0
- package/build/angular/components/keyboard-avoiding-view/index.js +11 -17
- package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
- package/build/angular/components/modal/index.d.ts +1 -0
- package/build/angular/components/modal/index.js +19 -12
- package/build/angular/components/modal/index.js.map +1 -1
- package/build/angular/components/pressable-props.d.ts +32 -0
- package/build/angular/components/pressable-props.js +11 -0
- package/build/angular/components/pressable-props.js.map +1 -0
- package/build/angular/components/refresh-control-props.d.ts +16 -0
- package/build/angular/components/refresh-control-props.js +14 -0
- package/build/angular/components/refresh-control-props.js.map +1 -0
- package/build/angular/components/safe-area-view-props.d.ts +7 -0
- package/build/angular/components/safe-area-view-props.js +11 -0
- package/build/angular/components/safe-area-view-props.js.map +1 -0
- package/build/angular/components/scroll-view-props.d.ts +76 -0
- package/build/angular/components/scroll-view-props.js +18 -0
- package/build/angular/components/scroll-view-props.js.map +1 -0
- package/build/angular/components/text-input-props.d.ts +45 -0
- package/build/angular/components/text-input-props.js +18 -0
- package/build/angular/components/text-input-props.js.map +1 -0
- package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +6 -0
- package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.js +2 -0
- package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.js.map +1 -0
- package/build/angular/components/touchable-props.d.ts +14 -0
- package/build/angular/components/touchable-props.js +13 -0
- package/build/angular/components/touchable-props.js.map +1 -0
- package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +3 -0
- package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.js +2 -0
- package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.js.map +1 -0
- package/build/angular/components/virtualized-list/index.d.ts +5 -1
- package/build/angular/components/virtualized-list/index.js +366 -280
- package/build/angular/components/virtualized-list/index.js.map +1 -1
- package/build/angular/components.d.ts +20 -26
- package/build/angular/components.js +12 -14
- package/build/angular/components.js.map +1 -1
- package/build/angular/create-portal/index.d.ts +2 -2
- package/build/angular/create-portal/index.js +5 -5
- package/build/angular/create-tunnel/index.js +1 -1
- package/build/angular/element-props.d.ts +53 -0
- package/build/angular/element-props.js +2 -0
- package/build/angular/element-props.js.map +1 -0
- package/build/angular/elements.d.ts +528 -0
- package/build/angular/elements.js +1444 -0
- package/build/angular/elements.js.map +1 -0
- package/build/angular/host-instance/index.js +1 -1
- package/build/angular/index.d.ts +4 -2
- package/build/angular/index.js +15 -1
- package/build/angular/index.js.map +1 -1
- package/build/angular/modules/animated/create-animated-component.d.ts +5 -6
- package/build/angular/modules/animated/create-animated-component.js +60 -73
- package/build/angular/modules/animated/create-animated-component.js.map +1 -1
- package/build/angular/modules/animated/index.js +1 -1
- package/build/angular/modules/animated/index.js.map +1 -1
- package/build/angular/modules/image/index.d.ts +3 -0
- package/build/angular/modules/image/index.js +16 -0
- package/build/angular/modules/image/index.js.map +1 -0
- package/build/angular/primitives/index.d.ts +18 -18
- package/build/angular/primitives/index.js +40 -36
- package/build/angular/primitives/index.js.map +1 -1
- package/build/angular/primitives/shared.d.ts +2 -3
- package/build/angular/primitives/shared.js +8 -53
- package/build/angular/primitives/shared.js.map +1 -1
- package/build/angular/register.d.ts +1 -1
- package/build/angular/register.js +12 -31
- package/build/angular/register.js.map +1 -1
- package/build/angular/render/index.js +3 -3
- package/build/angular/render/index.js.map +1 -1
- package/build/angular/renderer/index.js +113 -67
- package/build/angular/renderer/index.js.map +1 -1
- package/build/angular/renderer/value-change.d.ts +2 -0
- package/build/angular/renderer/value-change.js +9 -0
- package/build/angular/renderer/value-change.js.map +1 -0
- package/metro-config.cjs +54 -20
- package/metro-css-parser.cjs +2 -1
- package/package.json +5 -14
- package/src/anchor-host-registry.ts +1 -17
- package/src/change-detection-flush.ts +120 -0
- package/src/components/activity-indicator-props.ts +21 -0
- package/src/components/button-props.ts +26 -0
- package/src/components/flat-list/index.ts +12 -4
- package/src/components/image-background-props.ts +24 -0
- package/src/components/{image/shared.ts → image-shared.ts} +6 -1
- package/src/components/input-accessory-view-props.ts +21 -0
- package/src/components/keyboard-avoiding-view/index.ts +6 -9
- package/src/components/modal/index.ts +15 -7
- package/src/components/pressable-props.ts +73 -0
- package/src/components/refresh-control-props.ts +43 -0
- package/src/components/safe-area-view-props.ts +28 -0
- package/src/components/scroll-view-props.ts +109 -0
- package/src/components/text-input-props.ts +72 -0
- package/src/components/touchable-native-feedback/touchable-native-feedback-props.ts +23 -0
- package/src/components/touchable-props.ts +30 -0
- package/src/components/touchable-without-feedback/touchable-without-feedback-props.ts +21 -0
- package/src/components/virtualized-list/index.ts +239 -156
- package/src/components.ts +84 -35
- package/src/create-portal/index.ts +5 -5
- package/src/create-tunnel/index.ts +1 -1
- package/src/diagnostics.ts +1 -1
- package/src/element-props.ts +90 -0
- package/src/elements.ts +919 -0
- package/src/host-instance/index.ts +1 -1
- package/src/index.ts +52 -15
- package/src/modules/animated/create-animated-component.ts +50 -55
- package/src/modules/animated/index.ts +1 -1
- package/src/modules/image/index.ts +18 -0
- package/src/primitives/index.ts +22 -18
- package/src/primitives/shared.ts +11 -44
- package/src/register.ts +12 -40
- package/src/render/index.ts +3 -3
- package/src/renderer/index.ts +122 -73
- package/src/renderer/value-change.ts +8 -0
- package/babel-lower-host-primitives.cjs +0 -636
- package/build/angular/components/activity-indicator/index.android.d.ts +0 -13
- package/build/angular/components/activity-indicator/index.android.js +0 -29
- package/build/angular/components/activity-indicator/index.android.js.map +0 -1
- package/build/angular/components/activity-indicator/index.d.ts +0 -1
- package/build/angular/components/activity-indicator/index.ios.d.ts +0 -9
- package/build/angular/components/activity-indicator/index.ios.js +0 -26
- package/build/angular/components/activity-indicator/index.ios.js.map +0 -1
- package/build/angular/components/activity-indicator/index.js +0 -4
- package/build/angular/components/activity-indicator/index.js.map +0 -1
- package/build/angular/components/activity-indicator/shared.d.ts +0 -67
- package/build/angular/components/activity-indicator/shared.js +0 -260
- package/build/angular/components/activity-indicator/shared.js.map +0 -1
- package/build/angular/components/button.d.ts +0 -68
- package/build/angular/components/button.js +0 -360
- package/build/angular/components/button.js.map +0 -1
- package/build/angular/components/image/index.android.d.ts +0 -15
- package/build/angular/components/image/index.android.js +0 -83
- package/build/angular/components/image/index.android.js.map +0 -1
- package/build/angular/components/image/index.d.ts +0 -1
- package/build/angular/components/image/index.ios.d.ts +0 -15
- package/build/angular/components/image/index.ios.js +0 -83
- package/build/angular/components/image/index.ios.js.map +0 -1
- package/build/angular/components/image/index.js +0 -3
- package/build/angular/components/image/index.js.map +0 -1
- package/build/angular/components/image/shared.js.map +0 -1
- package/build/angular/components/image-background.d.ts +0 -85
- package/build/angular/components/image-background.js +0 -443
- package/build/angular/components/image-background.js.map +0 -1
- package/build/angular/components/input-accessory-view/index.d.ts +0 -66
- package/build/angular/components/input-accessory-view/index.js +0 -287
- package/build/angular/components/input-accessory-view/index.js.map +0 -1
- package/build/angular/components/pressable/index.d.ts +0 -134
- package/build/angular/components/pressable/index.js +0 -514
- package/build/angular/components/pressable/index.js.map +0 -1
- package/build/angular/components/refresh-control/index.d.ts +0 -91
- package/build/angular/components/refresh-control/index.js +0 -382
- package/build/angular/components/refresh-control/index.js.map +0 -1
- package/build/angular/components/safe-area-view/index.d.ts +0 -64
- package/build/angular/components/safe-area-view/index.js +0 -287
- package/build/angular/components/safe-area-view/index.js.map +0 -1
- package/build/angular/components/scroll-view/index.android.d.ts +0 -20
- package/build/angular/components/scroll-view/index.android.js +0 -262
- package/build/angular/components/scroll-view/index.android.js.map +0 -1
- package/build/angular/components/scroll-view/index.d.ts +0 -3
- package/build/angular/components/scroll-view/index.ios.d.ts +0 -8
- package/build/angular/components/scroll-view/index.ios.js +0 -92
- package/build/angular/components/scroll-view/index.ios.js.map +0 -1
- package/build/angular/components/scroll-view/index.js +0 -6
- package/build/angular/components/scroll-view/index.js.map +0 -1
- package/build/angular/components/scroll-view/projection.d.ts +0 -67
- package/build/angular/components/scroll-view/projection.js +0 -560
- package/build/angular/components/scroll-view/projection.js.map +0 -1
- package/build/angular/components/scroll-view/shared.d.ts +0 -241
- package/build/angular/components/scroll-view/shared.js +0 -848
- package/build/angular/components/scroll-view/shared.js.map +0 -1
- package/build/angular/components/scroll-view/sticky-header.d.ts +0 -40
- package/build/angular/components/scroll-view/sticky-header.js +0 -224
- package/build/angular/components/scroll-view/sticky-header.js.map +0 -1
- package/build/angular/components/switch/index.android.d.ts +0 -24
- package/build/angular/components/switch/index.android.js +0 -112
- package/build/angular/components/switch/index.android.js.map +0 -1
- package/build/angular/components/switch/index.d.ts +0 -1
- package/build/angular/components/switch/index.ios.d.ts +0 -23
- package/build/angular/components/switch/index.ios.js +0 -111
- package/build/angular/components/switch/index.ios.js.map +0 -1
- package/build/angular/components/switch/index.js +0 -4
- package/build/angular/components/switch/index.js.map +0 -1
- package/build/angular/components/switch/shared.d.ts +0 -49
- package/build/angular/components/switch/shared.js +0 -191
- package/build/angular/components/switch/shared.js.map +0 -1
- package/build/angular/components/text-input.d.ts +0 -167
- package/build/angular/components/text-input.js +0 -684
- package/build/angular/components/text-input.js.map +0 -1
- package/build/angular/components/touchable/index.d.ts +0 -283
- package/build/angular/components/touchable/index.js +0 -1453
- package/build/angular/components/touchable/index.js.map +0 -1
- package/build/angular/components/touchable-native-feedback/index.d.ts +0 -87
- package/build/angular/components/touchable-native-feedback/index.js +0 -409
- package/build/angular/components/touchable-native-feedback/index.js.map +0 -1
- package/build/angular/state-style.d.ts +0 -9
- package/build/angular/state-style.js +0 -39
- package/build/angular/state-style.js.map +0 -1
- package/metro-transformer.cjs +0 -69
- package/src/components/activity-indicator/index.android.ts +0 -23
- package/src/components/activity-indicator/index.ios.ts +0 -21
- package/src/components/activity-indicator/index.ts +0 -4
- package/src/components/activity-indicator/shared.ts +0 -225
- package/src/components/button.ts +0 -237
- package/src/components/image/index.android.ts +0 -95
- package/src/components/image/index.ios.ts +0 -95
- package/src/components/image/index.ts +0 -3
- package/src/components/image-background.ts +0 -308
- package/src/components/input-accessory-view/index.ts +0 -246
- package/src/components/pressable/index.ts +0 -522
- package/src/components/refresh-control/index.ts +0 -349
- package/src/components/safe-area-view/index.ts +0 -247
- package/src/components/scroll-view/index.android.ts +0 -205
- package/src/components/scroll-view/index.ios.ts +0 -81
- package/src/components/scroll-view/index.ts +0 -7
- package/src/components/scroll-view/projection.ts +0 -713
- package/src/components/scroll-view/shared.ts +0 -1093
- package/src/components/scroll-view/sticky-header.ts +0 -267
- package/src/components/switch/index.android.ts +0 -113
- package/src/components/switch/index.ios.ts +0 -112
- package/src/components/switch/index.ts +0 -4
- package/src/components/switch/shared.ts +0 -284
- package/src/components/text-input.ts +0 -669
- package/src/components/touchable/index.ts +0 -956
- package/src/components/touchable-native-feedback/index.ts +0 -327
- package/src/state-style.ts +0 -39
package/metro-transformer.cjs
DELETED
|
@@ -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,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
|
-
}
|
package/src/components/button.ts
DELETED
|
@@ -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
|
-
}
|