@symbiote-native/angular 3.3.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/babel-register-composed.cjs +1 -0
- package/build/angular/accessibility-inputs.d.ts +2 -1
- package/build/angular/accessibility-inputs.js +4 -1
- package/build/angular/accessibility-inputs.js.map +1 -1
- package/build/angular/callback-host.d.ts +1 -1
- package/build/angular/callback-host.js +57 -9
- package/build/angular/callback-host.js.map +1 -1
- package/build/angular/components/flat-list/flat-list-handle.d.ts +35 -0
- package/build/angular/components/flat-list/flat-list-handle.js +48 -0
- package/build/angular/components/flat-list/flat-list-handle.js.map +1 -0
- package/build/angular/components/flat-list/flat-list-template.d.ts +1 -1
- package/build/angular/components/flat-list/flat-list-template.js +16 -0
- package/build/angular/components/flat-list/flat-list-template.js.map +1 -1
- package/build/angular/components/flat-list/index.d.ts +6 -30
- package/build/angular/components/flat-list/index.js +6 -36
- package/build/angular/components/flat-list/index.js.map +1 -1
- package/build/angular/components/image-inputs.d.ts +4 -0
- package/build/angular/components/image-inputs.js +81 -0
- package/build/angular/components/image-inputs.js.map +1 -0
- package/build/angular/components/image-props-resolve.d.ts +3 -0
- package/build/angular/components/image-props-resolve.js +133 -0
- package/build/angular/components/image-props-resolve.js.map +1 -0
- package/build/angular/components/image-shared.d.ts +8 -6
- package/build/angular/components/image-shared.js +23 -212
- package/build/angular/components/image-shared.js.map +1 -1
- package/build/angular/components/input-accessory-view-props.d.ts +4 -4
- package/build/angular/components/keyboard-avoiding-view/index.d.ts +3 -6
- package/build/angular/components/keyboard-avoiding-view/index.js +29 -56
- package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
- package/build/angular/components/layout-conformance-props.d.ts +4 -0
- package/build/angular/components/layout-conformance-props.js +2 -0
- package/build/angular/components/layout-conformance-props.js.map +1 -0
- package/build/angular/components/modal/index.d.ts +6 -5
- package/build/angular/components/modal/index.js +17 -2
- package/build/angular/components/modal/index.js.map +1 -1
- package/build/angular/components/refresh-control-props.d.ts +7 -7
- package/build/angular/components/scroll-view-props.d.ts +8 -5
- package/build/angular/components/section-list/index.d.ts +17 -8
- package/build/angular/components/section-list/index.js +37 -28
- package/build/angular/components/section-list/index.js.map +1 -1
- package/build/angular/components/touchable-props.d.ts +2 -2
- package/build/angular/components/virtualized-list/cell-renderer-context.d.ts +12 -0
- package/build/angular/components/virtualized-list/cell-renderer-context.js +16 -0
- package/build/angular/components/virtualized-list/cell-renderer-context.js.map +1 -0
- package/build/angular/components/virtualized-list/directives.d.ts +26 -6
- package/build/angular/components/virtualized-list/directives.js +59 -5
- package/build/angular/components/virtualized-list/directives.js.map +1 -1
- package/build/angular/components/virtualized-list/index.d.ts +19 -15
- package/build/angular/components/virtualized-list/index.js +91 -61
- package/build/angular/components/virtualized-list/index.js.map +1 -1
- package/build/angular/components/virtualized-list/list-bags.d.ts +5 -1
- package/build/angular/components/virtualized-list/list-bags.js +31 -19
- package/build/angular/components/virtualized-list/list-bags.js.map +1 -1
- package/build/angular/components/virtualized-list/list-effects.d.ts +2 -2
- package/build/angular/components/virtualized-list/list-effects.js +17 -27
- package/build/angular/components/virtualized-list/list-effects.js.map +1 -1
- package/build/angular/components/virtualized-list/list-handle.d.ts +4 -1
- package/build/angular/components/virtualized-list/list-handle.js +13 -3
- package/build/angular/components/virtualized-list/list-handle.js.map +1 -1
- package/build/angular/components/virtualized-list/list-inputs.d.ts +19 -5
- package/build/angular/components/virtualized-list/list-inputs.js +47 -4
- package/build/angular/components/virtualized-list/list-inputs.js.map +1 -1
- package/build/angular/components/virtualized-list/list-props.d.ts +9 -3
- package/build/angular/components/virtualized-list/list-rows.d.ts +25 -0
- package/build/angular/components/virtualized-list/list-rows.js +25 -0
- package/build/angular/components/virtualized-list/list-rows.js.map +1 -0
- package/build/angular/components/virtualized-list/list-styles.d.ts +4 -0
- package/build/angular/components/virtualized-list/list-styles.js +10 -2
- package/build/angular/components/virtualized-list/list-styles.js.map +1 -1
- package/build/angular/components/virtualized-list/list-template.d.ts +1 -1
- package/build/angular/components/virtualized-list/list-template.js +159 -73
- package/build/angular/components/virtualized-list/list-template.js.map +1 -1
- package/build/angular/components/virtualized-list/nested-scope.d.ts +6 -0
- package/build/angular/components/virtualized-list/nested-scope.js +17 -0
- package/build/angular/components/virtualized-list/nested-scope.js.map +1 -0
- package/build/angular/components/virtualized-section-list/directives.d.ts +21 -9
- package/build/angular/components/virtualized-section-list/directives.js +8 -28
- package/build/angular/components/virtualized-section-list/directives.js.map +1 -1
- package/build/angular/components/virtualized-section-list/index.d.ts +39 -60
- package/build/angular/components/virtualized-section-list/index.js +67 -33
- package/build/angular/components/virtualized-section-list/index.js.map +1 -1
- package/build/angular/components/virtualized-section-list/section-cell.d.ts +29 -0
- package/build/angular/components/virtualized-section-list/section-cell.js +82 -0
- package/build/angular/components/virtualized-section-list/section-cell.js.map +1 -0
- package/build/angular/components/virtualized-section-list/section-list-props.d.ts +56 -0
- package/build/angular/components/virtualized-section-list/section-list-props.js +3 -0
- package/build/angular/components/virtualized-section-list/section-list-props.js.map +1 -0
- package/build/angular/components/virtualized-section-list/section-list-template.d.ts +1 -1
- package/build/angular/components/virtualized-section-list/section-list-template.js +34 -26
- package/build/angular/components/virtualized-section-list/section-list-template.js.map +1 -1
- package/build/angular/components.d.ts +7 -3
- package/build/angular/components.js +2 -1
- package/build/angular/components.js.map +1 -1
- package/build/angular/element-base.d.ts +17 -1
- package/build/angular/element-base.js +33 -1
- package/build/angular/element-base.js.map +1 -1
- package/build/angular/element-props.d.ts +7 -7
- package/build/angular/element-text-input-native.d.ts +27 -0
- package/build/angular/element-text-input-native.js +52 -0
- package/build/angular/element-text-input-native.js.map +1 -0
- package/build/angular/elements-controls.d.ts +8 -2
- package/build/angular/elements-controls.js +13 -1
- package/build/angular/elements-controls.js.map +1 -1
- package/build/angular/elements-layout.d.ts +20 -3
- package/build/angular/elements-layout.js +37 -3
- package/build/angular/elements-layout.js.map +1 -1
- package/build/angular/elements-press.d.ts +10 -3
- package/build/angular/elements-press.js +13 -1
- package/build/angular/elements-press.js.map +1 -1
- package/build/angular/elements.d.ts +3 -3
- package/build/angular/elements.js +3 -2
- package/build/angular/elements.js.map +1 -1
- package/build/angular/index.d.ts +15 -7
- package/build/angular/index.js +22 -25
- package/build/angular/index.js.map +1 -1
- package/build/angular/modules/animated/create-animated-component.d.ts +1 -1
- package/build/angular/modules/animated/create-animated-component.js +1 -1
- package/build/angular/modules/animated/create-animated-component.js.map +1 -1
- package/build/angular/modules/animated/index.d.ts +54 -41
- package/build/angular/modules/animated/index.js +2 -26
- package/build/angular/modules/animated/index.js.map +1 -1
- package/build/angular/modules/app-registry/index.d.ts +3 -3
- package/build/angular/modules/app-registry/index.js +2 -2
- package/build/angular/modules/app-registry/index.js.map +1 -1
- package/build/angular/modules/status-bar/index.d.ts +9 -5
- package/build/angular/modules/status-bar/index.js +21 -10
- package/build/angular/modules/status-bar/index.js.map +1 -1
- package/build/angular/primitives/index.d.ts +4 -0
- package/build/angular/primitives/index.js +12 -0
- package/build/angular/primitives/index.js.map +1 -1
- package/build/angular/render/index.d.ts +2 -2
- package/build/angular/render/index.js +10 -29
- package/build/angular/render/index.js.map +1 -1
- package/build/angular/root-tag.d.ts +4 -0
- package/build/angular/root-tag.js +10 -0
- package/build/angular/root-tag.js.map +1 -0
- package/build/angular/services/color-scheme.service.d.ts +1 -1
- package/package.json +6 -6
- package/src/accessibility-inputs.ts +3 -0
- package/src/callback-host.ts +56 -8
- package/src/components/flat-list/flat-list-handle.ts +64 -0
- package/src/components/flat-list/flat-list-template.ts +16 -0
- package/src/components/flat-list/index.ts +6 -48
- package/src/components/image-inputs.ts +94 -0
- package/src/components/image-props-resolve.ts +172 -0
- package/src/components/image-shared.ts +26 -291
- package/src/components/input-accessory-view-props.ts +12 -8
- package/src/components/keyboard-avoiding-view/index.ts +39 -79
- package/src/components/layout-conformance-props.ts +8 -0
- package/src/components/modal/index.ts +42 -20
- package/src/components/refresh-control-props.ts +29 -25
- package/src/components/scroll-view-props.ts +84 -76
- package/src/components/section-list/index.ts +34 -37
- package/src/components/touchable-props.ts +6 -2
- package/src/components/virtualized-list/cell-renderer-context.ts +36 -0
- package/src/components/virtualized-list/directives.ts +84 -8
- package/src/components/virtualized-list/index.ts +118 -85
- package/src/components/virtualized-list/list-bags.ts +38 -19
- package/src/components/virtualized-list/list-effects.ts +20 -32
- package/src/components/virtualized-list/list-handle.ts +17 -4
- package/src/components/virtualized-list/list-inputs.ts +47 -0
- package/src/components/virtualized-list/list-props.ts +57 -50
- package/src/components/virtualized-list/list-rows.ts +66 -0
- package/src/components/virtualized-list/list-styles.ts +30 -1
- package/src/components/virtualized-list/list-template.ts +159 -73
- package/src/components/virtualized-list/nested-scope.ts +22 -0
- package/src/components/virtualized-section-list/directives.ts +41 -40
- package/src/components/virtualized-section-list/index.ts +114 -118
- package/src/components/virtualized-section-list/section-cell.ts +109 -0
- package/src/components/virtualized-section-list/section-list-props.ts +79 -0
- package/src/components/virtualized-section-list/section-list-template.ts +34 -26
- package/src/components.ts +8 -0
- package/src/element-base.ts +17 -0
- package/src/element-props.ts +35 -33
- package/src/element-text-input-native.ts +31 -0
- package/src/elements-controls.ts +9 -1
- package/src/elements-layout.ts +27 -0
- package/src/elements-press.ts +10 -2
- package/src/elements.ts +3 -0
- package/src/index.ts +79 -22
- package/src/modules/animated/index.ts +2 -47
- package/src/modules/app-registry/index.ts +3 -1
- package/src/modules/status-bar/index.ts +24 -11
- package/src/primitives/index.ts +7 -0
- package/src/render/index.ts +23 -50
- package/src/root-tag.ts +14 -0
- package/src/services/color-scheme.service.ts +1 -1
|
@@ -25,12 +25,8 @@ import {
|
|
|
25
25
|
type OnInit,
|
|
26
26
|
} from '@angular/core';
|
|
27
27
|
import {
|
|
28
|
-
|
|
29
|
-
configureKeyboardAvoidingAnimation,
|
|
28
|
+
createKeyboardAvoidingModel,
|
|
30
29
|
keyboardAvoidingEventNamesFor,
|
|
31
|
-
readKeyboardAnimationTiming,
|
|
32
|
-
readKeyboardFrame,
|
|
33
|
-
readLayoutFrame,
|
|
34
30
|
readPrefersCrossFadeTransitions,
|
|
35
31
|
resolveAccessibilityProps,
|
|
36
32
|
resolveKeyboardAvoidingLayout,
|
|
@@ -39,12 +35,10 @@ import {
|
|
|
39
35
|
type IAriaProps,
|
|
40
36
|
type IKeyboardAvoidingBehavior,
|
|
41
37
|
type IKeyboardAvoidingLayout,
|
|
42
|
-
type IMeasuredFrame,
|
|
43
38
|
} from '@symbiote-native/components';
|
|
44
39
|
import {
|
|
45
40
|
Keyboard,
|
|
46
41
|
Platform,
|
|
47
|
-
dlog,
|
|
48
42
|
isSymbioteEvent,
|
|
49
43
|
type IEventSubscription,
|
|
50
44
|
type IStyleProp,
|
|
@@ -64,15 +58,15 @@ export type { IKeyboardAvoidingBehavior } from '@symbiote-native/components';
|
|
|
64
58
|
// Mirrors React's IKeyboardAvoidingViewProps minus children (Angular takes children via
|
|
65
59
|
// <ng-content>), declared per-adapter over the shared accessibility base since a framework-specific
|
|
66
60
|
// children field keeps it from being fully shared across adapters.
|
|
67
|
-
export
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
61
|
+
export type IAngularKeyboardAvoidingViewProps = IAccessibilityProps &
|
|
62
|
+
IAriaProps & {
|
|
63
|
+
behavior?: IKeyboardAvoidingBehavior;
|
|
64
|
+
enabled?: boolean;
|
|
65
|
+
keyboardVerticalOffset?: number;
|
|
66
|
+
contentContainerStyle?: IStyleProp<IViewStyle>;
|
|
67
|
+
style?: IStyleProp<IViewStyle>;
|
|
68
|
+
onLayout?: (event: ISymbioteEvent) => void;
|
|
69
|
+
};
|
|
76
70
|
|
|
77
71
|
// What the component itself takes as plain @Input()s: the full surface minus onLayout and the
|
|
78
72
|
// accessibility callbacks, which it exposes as real @Output() EventEmitters instead (see the
|
|
@@ -133,36 +127,41 @@ export class KeyboardAvoidingView
|
|
|
133
127
|
@Input() testID?: string;
|
|
134
128
|
@Input() nativeID?: string;
|
|
135
129
|
|
|
136
|
-
//
|
|
137
|
-
// OnPush + zoneless means a keyboard event mutates it and pulls the view via markForCheck.
|
|
130
|
+
// Plain field, the model sets it and `markForCheck` pulls the OnPush view
|
|
138
131
|
private inset = 0;
|
|
139
|
-
//
|
|
140
|
-
// keyboard event's inset math (React's frameRef / initialHeightRef, Vue's frame / initialHeight).
|
|
141
|
-
private frame?: IMeasuredFrame;
|
|
142
|
-
private initialHeight?: number;
|
|
143
|
-
// The iOS "Prefer Cross-Fade Transitions" setting, read once per mount. Deliberately a plain
|
|
144
|
-
// field and NOT markForCheck'd when the promise lands: it is a device setting that cannot change
|
|
145
|
-
// mid-session, and it feeds only the NEXT keyboard event's math — never the current render — so
|
|
146
|
-
// under zoneless CD there is nothing to repaint at resolve time. The keyboard event that does use
|
|
147
|
-
// it already calls markForCheck itself.
|
|
132
|
+
// A device setting that cannot change mid-session, learning it must not repaint
|
|
148
133
|
private prefersCrossFadeTransitions = false;
|
|
149
134
|
private subscriptions: IEventSubscription[] = [];
|
|
150
135
|
|
|
151
136
|
private readonly changeDetector = inject(ChangeDetectorRef);
|
|
152
|
-
// This component's
|
|
153
|
-
// onto (see anchorHostStyle's doc comment) — NOT a ViewChild into the inner view (this
|
|
154
|
-
// component has none; the wrapper IS the outer template node hostProps binds onto).
|
|
137
|
+
// This component's own host, the anchor that `class` at the use site resolves onto
|
|
155
138
|
private readonly elementRef = inject(ElementRef);
|
|
156
139
|
|
|
140
|
+
// Options are read at event time, т.к. an `@Input` can change under a live subscription
|
|
141
|
+
private readonly model = createKeyboardAvoidingModel({
|
|
142
|
+
options: () => ({
|
|
143
|
+
behavior: this.behavior,
|
|
144
|
+
enabled: this.enabled !== false,
|
|
145
|
+
keyboardVerticalOffset:
|
|
146
|
+
this.keyboardVerticalOffset ?? DEFAULT_VERTICAL_OFFSET,
|
|
147
|
+
}),
|
|
148
|
+
setInset: value => {
|
|
149
|
+
this.inset = value;
|
|
150
|
+
this.changeDetector.markForCheck();
|
|
151
|
+
},
|
|
152
|
+
prefersCrossFade: () => this.prefersCrossFadeTransitions,
|
|
153
|
+
});
|
|
154
|
+
|
|
157
155
|
ngOnInit(): void {
|
|
158
|
-
//
|
|
159
|
-
// the keyboard animation, Android the did* pair. The change-frame notification is deliberately
|
|
160
|
-
// absent — with an undocked/split/floating iOS keyboard it fires BEFORE the hide, so listening
|
|
161
|
-
// to it applies a frame captured mid-dismissal (RN KeyboardAvoidingView.js's own comment).
|
|
156
|
+
// iOS takes the `will*` pair so the view rides up with the keyboard, Android the `did*` pair
|
|
162
157
|
const events = keyboardAvoidingEventNamesFor(Platform.OS);
|
|
163
158
|
this.subscriptions = [
|
|
164
|
-
Keyboard.addListener(events.show, payload =>
|
|
165
|
-
|
|
159
|
+
Keyboard.addListener(events.show, payload => {
|
|
160
|
+
this.model.keyboardShown(payload);
|
|
161
|
+
// An unchanged inset skips `setInset`, the event still has to carry a new `@Input` down
|
|
162
|
+
this.changeDetector.markForCheck();
|
|
163
|
+
}),
|
|
164
|
+
Keyboard.addListener(events.hide, this.model.keyboardHidden),
|
|
166
165
|
];
|
|
167
166
|
// The core wrapper, not AccessibilityInfo directly: the engine's iOS getter REJECTS on a
|
|
168
167
|
// native error (RN parity), and nobody awaits this read, so an unwrapped call would surface
|
|
@@ -177,47 +176,10 @@ export class KeyboardAvoidingView
|
|
|
177
176
|
this.subscriptions = [];
|
|
178
177
|
}
|
|
179
178
|
|
|
180
|
-
|
|
181
|
-
const keyboard = readKeyboardFrame(payload);
|
|
182
|
-
const offset = this.keyboardVerticalOffset ?? DEFAULT_VERTICAL_OFFSET;
|
|
183
|
-
const next = computeInset(this.frame, keyboard, offset, {
|
|
184
|
-
// Read off the field at event time, not captured when the subscription was built: `behavior`
|
|
185
|
-
// is an @Input that can change under a long-lived subscription, and a stale one keeps
|
|
186
|
-
// applying the old mode's math (it gates the previous-inset correction below).
|
|
187
|
-
behavior: this.behavior,
|
|
188
|
-
// The inset CURRENTLY applied (RN's this.state.bottom), read off the field at event time so
|
|
189
|
-
// 'height' mode's fixpoint correction sees the live value: that mode SHRINKS the wrapper by
|
|
190
|
-
// the inset, so the next onLayout reports a frame shorter by exactly that much.
|
|
191
|
-
previousInset: this.inset,
|
|
192
|
-
prefersCrossFadeTransitions: this.prefersCrossFadeTransitions,
|
|
193
|
-
});
|
|
194
|
-
// RN's `_updateBottomIfNecessary` skips the animation when the inset did not change.
|
|
195
|
-
if (next !== this.inset)
|
|
196
|
-
configureKeyboardAvoidingAnimation(
|
|
197
|
-
readKeyboardAnimationTiming(payload),
|
|
198
|
-
this.enabled !== false,
|
|
199
|
-
);
|
|
200
|
-
dlog(`KeyboardAvoidingView show -> inset ${next}`);
|
|
201
|
-
this.inset = next;
|
|
202
|
-
this.changeDetector.markForCheck();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
private onHide(): void {
|
|
206
|
-
dlog('KeyboardAvoidingView hide -> inset 0');
|
|
207
|
-
this.inset = 0;
|
|
208
|
-
this.changeDetector.markForCheck();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// The wrapper's onLayout measures the frame BEFORE forwarding to the caller's onLayout, so the
|
|
212
|
-
// next keyboard event's inset math has the view's real position (React/Vue's handleLayout).
|
|
179
|
+
// Measured before the caller's `layout` output fires
|
|
213
180
|
handleLayout(event: unknown): void {
|
|
214
181
|
if (!isSymbioteEvent(event)) return;
|
|
215
|
-
|
|
216
|
-
if (measured !== undefined) {
|
|
217
|
-
this.frame = measured;
|
|
218
|
-
if (this.initialHeight === undefined)
|
|
219
|
-
this.initialHeight = measured.height;
|
|
220
|
-
}
|
|
182
|
+
this.model.laidOut(event.nativeEvent.layout);
|
|
221
183
|
this.layout.emit(event);
|
|
222
184
|
}
|
|
223
185
|
|
|
@@ -227,14 +189,12 @@ export class KeyboardAvoidingView
|
|
|
227
189
|
return this.enabled === false ? 0 : this.inset;
|
|
228
190
|
}
|
|
229
191
|
|
|
230
|
-
//
|
|
231
|
-
// of RN's render). Recomputed per CD pass, the Angular twin of React/Vue's per-render call.
|
|
232
|
-
// Named `resolvedLayout`, not `layout` — that name is now the onLayout @Output() EventEmitter.
|
|
192
|
+
// Not `layout`, that name is the `onLayout` output
|
|
233
193
|
private get resolvedLayout(): IKeyboardAvoidingLayout {
|
|
234
194
|
return resolveKeyboardAvoidingLayout({
|
|
235
195
|
behavior: this.behavior,
|
|
236
196
|
effectiveInset: this.effectiveInset,
|
|
237
|
-
initialHeight: this.initialHeight,
|
|
197
|
+
initialHeight: this.model.initialHeight(),
|
|
238
198
|
style: this.style,
|
|
239
199
|
contentContainerStyle: this.contentContainerStyle,
|
|
240
200
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// The prop surface of `<layout-conformance>`, RN's `experimental_LayoutConformance`, for Angular
|
|
2
|
+
// Children come through `<ng-content>`, so there is no `children` here
|
|
3
|
+
import type { ILayoutConformanceMode } from '@symbiote-native/components';
|
|
4
|
+
|
|
5
|
+
export type IAngularLayoutConformanceProps = {
|
|
6
|
+
// `strict` lays out by the W3C spec even where it breaks compatibility
|
|
7
|
+
mode: ILayoutConformanceMode;
|
|
8
|
+
};
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
renderModal,
|
|
32
32
|
resolveAccessibilityProps,
|
|
33
33
|
shouldRenderModal,
|
|
34
|
+
warnAboutModalProps,
|
|
34
35
|
type IAccessibilityProps,
|
|
35
36
|
type IAriaProps,
|
|
36
37
|
type IModalAnimationType,
|
|
@@ -42,11 +43,16 @@ import {
|
|
|
42
43
|
dlog,
|
|
43
44
|
isSymbioteEvent,
|
|
44
45
|
Platform,
|
|
46
|
+
type IColorValue,
|
|
45
47
|
type IStyleProp,
|
|
46
48
|
type ISymbioteEvent,
|
|
47
49
|
type IViewStyle,
|
|
48
50
|
} from '@symbiote-native/engine';
|
|
49
51
|
import { AccessibilityEventsBase } from '../../accessibility-events';
|
|
52
|
+
import {
|
|
53
|
+
ListScopeProvider,
|
|
54
|
+
NO_LIST_SCOPE,
|
|
55
|
+
} from '../virtualized-list/nested-scope';
|
|
50
56
|
import {
|
|
51
57
|
anchorHostStyle,
|
|
52
58
|
ModalHost,
|
|
@@ -63,25 +69,26 @@ export type {
|
|
|
63
69
|
} from '@symbiote-native/components';
|
|
64
70
|
|
|
65
71
|
// Mirrors React's IModalProps minus children (Angular takes children via <ng-content>).
|
|
66
|
-
export
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
export type IAngularModalProps = IAccessibilityProps &
|
|
73
|
+
IAriaProps & {
|
|
74
|
+
visible?: boolean;
|
|
75
|
+
transparent?: boolean;
|
|
76
|
+
backdropColor?: IColorValue;
|
|
77
|
+
animationType?: IModalAnimationType;
|
|
78
|
+
presentationStyle?: IModalPresentationStyle;
|
|
79
|
+
supportedOrientations?: ReadonlyArray<IModalOrientation>;
|
|
80
|
+
hardwareAccelerated?: boolean;
|
|
81
|
+
statusBarTranslucent?: boolean;
|
|
82
|
+
navigationBarTranslucent?: boolean;
|
|
83
|
+
allowSwipeDismissal?: boolean;
|
|
84
|
+
onShow?: () => void;
|
|
85
|
+
onDismiss?: () => void;
|
|
86
|
+
onRequestClose?: () => void;
|
|
87
|
+
// The engine hands every listener the ISymbioteEvent wrapper, so the orientation is read at
|
|
88
|
+
// event.nativeEvent.orientation (IModalOrientationChangeEvent describes that payload).
|
|
89
|
+
onOrientationChange?: (event: ISymbioteEvent) => void;
|
|
90
|
+
style?: IStyleProp<IViewStyle>;
|
|
91
|
+
};
|
|
85
92
|
|
|
86
93
|
// What the Modal component itself takes as plain @Input()s: the full surface minus the
|
|
87
94
|
// show/dismiss/close/orientation and accessibility events, which it exposes as real @Output()
|
|
@@ -107,6 +114,8 @@ export type IAngularModalInputs = Omit<
|
|
|
107
114
|
],
|
|
108
115
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
109
116
|
imports: [ModalHost, ViewHost, SymbioteHostPropsDirective],
|
|
117
|
+
// The content sits outside the list's scroll, so a list in it is not nested in that list
|
|
118
|
+
providers: [{ provide: ListScopeProvider, useValue: NO_LIST_SCOPE }],
|
|
110
119
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
111
120
|
template: `
|
|
112
121
|
@if (shouldRender) {
|
|
@@ -133,7 +142,7 @@ export class Modal
|
|
|
133
142
|
@Output() readonly requestClose = new EventEmitter<void>();
|
|
134
143
|
@Input() visible?: boolean;
|
|
135
144
|
@Input() transparent?: boolean;
|
|
136
|
-
@Input() backdropColor?:
|
|
145
|
+
@Input() backdropColor?: IColorValue;
|
|
137
146
|
@Input() animationType?: IModalAnimationType;
|
|
138
147
|
@Input() presentationStyle?: IModalPresentationStyle;
|
|
139
148
|
@Input() supportedOrientations?: ReadonlyArray<IModalOrientation>;
|
|
@@ -160,6 +169,18 @@ export class Modal
|
|
|
160
169
|
this.state = createInitialModalState(isModalVisible(this.visible));
|
|
161
170
|
}
|
|
162
171
|
|
|
172
|
+
// RN checks on mount and on every update, a dev build only
|
|
173
|
+
private warnOnMisuse(): void {
|
|
174
|
+
warnAboutModalProps({
|
|
175
|
+
presentationStyle: this.presentationStyle,
|
|
176
|
+
transparent: this.transparent,
|
|
177
|
+
navigationBarTranslucent: this.navigationBarTranslucent,
|
|
178
|
+
statusBarTranslucent: this.statusBarTranslucent,
|
|
179
|
+
allowSwipeDismissal: this.allowSwipeDismissal,
|
|
180
|
+
onRequestClose: this.requestClose.observed,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
163
184
|
// Bridges the non-reactive @Input fields `hostProps` reads into the reactive graph, so it can
|
|
164
185
|
// memoize. Plain fields read inside a computed() are UNTRACKED - something must signal "a
|
|
165
186
|
// dependency changed" or the bag goes stale. Signal inputs would do this natively, but `input()`
|
|
@@ -174,6 +195,7 @@ export class Modal
|
|
|
174
195
|
// Before the keep-alive early-return below: this is the single moment Angular has finished
|
|
175
196
|
// writing every changed @Input, and `hostProps` depends on far more than `visible`.
|
|
176
197
|
this.hostPropsRevision.update(revision => revision + 1);
|
|
198
|
+
this.warnOnMisuse();
|
|
177
199
|
const visibleChange = changes.visible;
|
|
178
200
|
// First change is reflected by the ngOnInit seed; only later toggles drive the keep-alive.
|
|
179
201
|
if (visibleChange === undefined || visibleChange.firstChange) return;
|
|
@@ -13,29 +13,33 @@ import type {
|
|
|
13
13
|
IAccessibilityProps,
|
|
14
14
|
IAriaProps,
|
|
15
15
|
} from '@symbiote-native/components';
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
IColorValue,
|
|
18
|
+
IStyleProp,
|
|
19
|
+
IViewStyle,
|
|
20
|
+
} from '@symbiote-native/engine';
|
|
17
21
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
22
|
+
export type IAngularRefreshControlProps = IAccessibilityProps &
|
|
23
|
+
IAriaProps & {
|
|
24
|
+
refreshing: boolean;
|
|
25
|
+
// `id` — RN's W3C alias for `nativeID`, folded by the spec entry's ID_ALIAS.
|
|
26
|
+
id?: string;
|
|
27
|
+
// RN's onRefresh is `() => void | Promise<void>`, the handler may be async; the promise is
|
|
28
|
+
// fire-and-forget (native already starts refreshing on the gesture).
|
|
29
|
+
onRefresh?: () => void | Promise<void>;
|
|
30
|
+
tintColor?: IColorValue;
|
|
31
|
+
title?: string;
|
|
32
|
+
titleColor?: IColorValue;
|
|
33
|
+
progressViewOffset?: number;
|
|
34
|
+
// Android-only spinner styling (RN RefreshControlPropsAndroid): `colors` are the indicator's
|
|
35
|
+
// animated stroke colors, `progressBackgroundColor` the disc behind it, `size` the diameter
|
|
36
|
+
// preset. AndroidSwipeRefreshLayout reads them; PullToRefreshView on iOS ignores unknown props.
|
|
37
|
+
colors?: readonly IColorValue[];
|
|
38
|
+
progressBackgroundColor?: IColorValue;
|
|
39
|
+
size?: 'default' | 'large';
|
|
40
|
+
// Android-only native prop forwarded to AndroidSwipeRefreshLayout; iOS native never reads it.
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
// The Android scroll-view wrap injects the layout half of the style onto this host; iOS leaves it
|
|
43
|
+
// unset (the RefreshControl is a childless sibling). Harmless to forward on both.
|
|
44
|
+
style?: IStyleProp<IViewStyle>;
|
|
45
|
+
};
|
|
@@ -15,8 +15,11 @@
|
|
|
15
15
|
import type {
|
|
16
16
|
IAccessibilityProps,
|
|
17
17
|
IAriaProps,
|
|
18
|
+
IInnerViewRef,
|
|
19
|
+
IScrollViewNativeOnlyProps,
|
|
18
20
|
} from '@symbiote-native/components';
|
|
19
21
|
import type {
|
|
22
|
+
IColorValue,
|
|
20
23
|
IStyleProp,
|
|
21
24
|
ISymbioteEvent,
|
|
22
25
|
IViewStyle,
|
|
@@ -27,80 +30,85 @@ export type { IScrollViewHandle } from '@symbiote-native/components';
|
|
|
27
30
|
type IScrollHandler = (event: ISymbioteEvent) => void;
|
|
28
31
|
type IContentSizeHandler = (width: number, height: number) => void;
|
|
29
32
|
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
export type IAngularScrollViewProps = IAccessibilityProps &
|
|
34
|
+
IAriaProps &
|
|
35
|
+
IScrollViewNativeOnlyProps & {
|
|
36
|
+
style?: IStyleProp<IViewStyle>;
|
|
37
|
+
// A bare string resolves through the shared style registry, like `class` on the host node.
|
|
38
|
+
contentContainerStyle?: IStyleProp<IViewStyle> | string;
|
|
39
|
+
scrollEnabled?: boolean;
|
|
40
|
+
showsVerticalScrollIndicator?: boolean;
|
|
41
|
+
showsHorizontalScrollIndicator?: boolean;
|
|
42
|
+
pagingEnabled?: boolean;
|
|
43
|
+
bounces?: boolean;
|
|
44
|
+
decelerationRate?: 'normal' | 'fast' | number;
|
|
45
|
+
scrollEventThrottle?: number;
|
|
46
|
+
contentInset?: {
|
|
47
|
+
top?: number;
|
|
48
|
+
left?: number;
|
|
49
|
+
bottom?: number;
|
|
50
|
+
right?: number;
|
|
51
|
+
};
|
|
52
|
+
contentOffset?: { x: number; y: number };
|
|
53
|
+
removeClippedSubviews?: boolean;
|
|
54
|
+
snapToInterval?: number;
|
|
55
|
+
snapToOffsets?: number[];
|
|
56
|
+
snapToAlignment?: 'start' | 'center' | 'end';
|
|
57
|
+
snapToStart?: boolean;
|
|
58
|
+
snapToEnd?: boolean;
|
|
59
|
+
disableIntervalMomentum?: boolean;
|
|
60
|
+
experimental_endDraggingSensitivityMultiplier?: number;
|
|
61
|
+
// Sticky headers: RN implements stickiness PURELY IN JS — the native scroll view does not honor
|
|
62
|
+
// an index array. The engine's behavior resolves the indices against its own content children.
|
|
63
|
+
stickyHeaderIndices?: number[];
|
|
64
|
+
invertStickyHeaders?: boolean;
|
|
65
|
+
stickyHeaderHiddenOnScroll?: boolean;
|
|
66
|
+
// Gets the content view after the first commit and null when it goes away
|
|
67
|
+
innerViewRef?: IInnerViewRef;
|
|
68
|
+
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
69
|
+
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
70
|
+
maintainVisibleContentPosition?: {
|
|
71
|
+
minIndexForVisible: number;
|
|
72
|
+
autoscrollToTopThreshold?: number;
|
|
73
|
+
};
|
|
74
|
+
// iOS-only forwarding props (harmless on Android: its manager ignores unknown props).
|
|
75
|
+
alwaysBounceHorizontal?: boolean;
|
|
76
|
+
alwaysBounceVertical?: boolean;
|
|
77
|
+
centerContent?: boolean;
|
|
78
|
+
scrollIndicatorInsets?: {
|
|
79
|
+
top?: number;
|
|
80
|
+
left?: number;
|
|
81
|
+
bottom?: number;
|
|
82
|
+
right?: number;
|
|
83
|
+
};
|
|
84
|
+
indicatorStyle?: 'default' | 'black' | 'white';
|
|
85
|
+
directionalLockEnabled?: boolean;
|
|
86
|
+
automaticallyAdjustKeyboardInsets?: boolean;
|
|
87
|
+
contentInsetAdjustmentBehavior?:
|
|
88
|
+
'automatic' | 'scrollableAxes' | 'never' | 'always';
|
|
89
|
+
minimumZoomScale?: number;
|
|
90
|
+
maximumZoomScale?: number;
|
|
91
|
+
zoomScale?: number;
|
|
92
|
+
bouncesZoom?: boolean;
|
|
93
|
+
pinchGestureEnabled?: boolean;
|
|
94
|
+
// Android-only forwarding props (harmless on iOS).
|
|
95
|
+
nestedScrollEnabled?: boolean;
|
|
96
|
+
overScrollMode?: 'auto' | 'always' | 'never';
|
|
97
|
+
fadingEdgeLength?: number;
|
|
98
|
+
persistentScrollbar?: boolean;
|
|
99
|
+
endFillColor?: IColorValue;
|
|
100
|
+
onLayout?: IScrollHandler;
|
|
101
|
+
onScroll?: IScrollHandler;
|
|
102
|
+
onScrollBeginDrag?: IScrollHandler;
|
|
103
|
+
onScrollEndDrag?: IScrollHandler;
|
|
104
|
+
onMomentumScrollBegin?: IScrollHandler;
|
|
105
|
+
onMomentumScrollEnd?: IScrollHandler;
|
|
106
|
+
// iOS-only: user tapped the status bar to scroll to top. Inert on Android.
|
|
107
|
+
onScrollToTop?: IScrollHandler;
|
|
108
|
+
// Synthesized in JS from the content view's onLayout (RN _handleContentOnLayout); deduped.
|
|
109
|
+
onContentSizeChange?: IContentSizeHandler;
|
|
110
|
+
onAccessibilityAction?: (event: ISymbioteEvent) => void;
|
|
111
|
+
onAccessibilityTap?: (event: ISymbioteEvent) => void;
|
|
112
|
+
onMagicTap?: (event: ISymbioteEvent) => void;
|
|
113
|
+
onAccessibilityEscape?: (event: ISymbioteEvent) => void;
|
|
47
114
|
};
|
|
48
|
-
contentOffset?: { x: number; y: number };
|
|
49
|
-
removeClippedSubviews?: boolean;
|
|
50
|
-
snapToInterval?: number;
|
|
51
|
-
snapToOffsets?: number[];
|
|
52
|
-
snapToAlignment?: 'start' | 'center' | 'end';
|
|
53
|
-
snapToStart?: boolean;
|
|
54
|
-
snapToEnd?: boolean;
|
|
55
|
-
disableIntervalMomentum?: boolean;
|
|
56
|
-
// Sticky headers: RN implements stickiness PURELY IN JS — the native scroll view does not honor
|
|
57
|
-
// an index array. The engine's behavior resolves the indices against its own content children.
|
|
58
|
-
stickyHeaderIndices?: number[];
|
|
59
|
-
invertStickyHeaders?: boolean;
|
|
60
|
-
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
61
|
-
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
62
|
-
maintainVisibleContentPosition?: {
|
|
63
|
-
minIndexForVisible: number;
|
|
64
|
-
autoscrollToTopThreshold?: number;
|
|
65
|
-
};
|
|
66
|
-
// iOS-only forwarding props (harmless on Android: its manager ignores unknown props).
|
|
67
|
-
alwaysBounceHorizontal?: boolean;
|
|
68
|
-
alwaysBounceVertical?: boolean;
|
|
69
|
-
centerContent?: boolean;
|
|
70
|
-
scrollIndicatorInsets?: {
|
|
71
|
-
top?: number;
|
|
72
|
-
left?: number;
|
|
73
|
-
bottom?: number;
|
|
74
|
-
right?: number;
|
|
75
|
-
};
|
|
76
|
-
indicatorStyle?: 'default' | 'black' | 'white';
|
|
77
|
-
directionalLockEnabled?: boolean;
|
|
78
|
-
automaticallyAdjustKeyboardInsets?: boolean;
|
|
79
|
-
contentInsetAdjustmentBehavior?:
|
|
80
|
-
'automatic' | 'scrollableAxes' | 'never' | 'always';
|
|
81
|
-
minimumZoomScale?: number;
|
|
82
|
-
maximumZoomScale?: number;
|
|
83
|
-
zoomScale?: number;
|
|
84
|
-
bouncesZoom?: boolean;
|
|
85
|
-
pinchGestureEnabled?: boolean;
|
|
86
|
-
// Android-only forwarding props (harmless on iOS).
|
|
87
|
-
nestedScrollEnabled?: boolean;
|
|
88
|
-
overScrollMode?: 'auto' | 'always' | 'never';
|
|
89
|
-
fadingEdgeLength?: number;
|
|
90
|
-
persistentScrollbar?: boolean;
|
|
91
|
-
endFillColor?: string;
|
|
92
|
-
onLayout?: IScrollHandler;
|
|
93
|
-
onScroll?: IScrollHandler;
|
|
94
|
-
onScrollBeginDrag?: IScrollHandler;
|
|
95
|
-
onScrollEndDrag?: IScrollHandler;
|
|
96
|
-
onMomentumScrollBegin?: IScrollHandler;
|
|
97
|
-
onMomentumScrollEnd?: IScrollHandler;
|
|
98
|
-
// iOS-only: user tapped the status bar to scroll to top. Inert on Android.
|
|
99
|
-
onScrollToTop?: IScrollHandler;
|
|
100
|
-
// Synthesized in JS from the content view's onLayout (RN _handleContentOnLayout); deduped.
|
|
101
|
-
onContentSizeChange?: IContentSizeHandler;
|
|
102
|
-
onAccessibilityAction?: (event: ISymbioteEvent) => void;
|
|
103
|
-
onAccessibilityTap?: (event: ISymbioteEvent) => void;
|
|
104
|
-
onMagicTap?: (event: ISymbioteEvent) => void;
|
|
105
|
-
onAccessibilityEscape?: (event: ISymbioteEvent) => void;
|
|
106
|
-
}
|