@ng-native/components 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +78 -1
- package/dist/activity-indicator.d.ts +41 -0
- package/dist/activity-indicator.js +66 -0
- package/dist/activity-indicator.js.map +1 -0
- package/dist/animated-style.d.ts +31 -0
- package/dist/animated-style.js +102 -0
- package/dist/animated-style.js.map +1 -0
- package/dist/animated.d.ts +125 -0
- package/dist/animated.js +538 -0
- package/dist/animated.js.map +1 -0
- package/dist/animation.d.ts +40 -0
- package/dist/animation.js +20 -0
- package/dist/animation.js.map +1 -0
- package/dist/animations-web.d.ts +8 -0
- package/dist/animations-web.js +31 -0
- package/dist/animations-web.js.map +1 -0
- package/dist/animations.d.ts +7 -0
- package/dist/animations.js +58 -0
- package/dist/animations.js.map +1 -0
- package/dist/controlled-model.d.ts +33 -0
- package/dist/controlled-model.js +47 -0
- package/dist/controlled-model.js.map +1 -0
- package/dist/easing.d.ts +21 -0
- package/dist/easing.js +50 -0
- package/dist/easing.js.map +1 -0
- package/dist/events.d.ts +169 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/gesture-backend.d.ts +26 -0
- package/dist/gesture-backend.js +14 -0
- package/dist/gesture-backend.js.map +1 -0
- package/dist/gesture-dispatch.d.ts +67 -0
- package/dist/gesture-dispatch.js +106 -0
- package/dist/gesture-dispatch.js.map +1 -0
- package/dist/gestures.d.ts +23 -0
- package/dist/gestures.js +164 -0
- package/dist/gestures.js.map +1 -0
- package/dist/height-index.d.ts +31 -0
- package/dist/height-index.js +80 -0
- package/dist/height-index.js.map +1 -0
- package/dist/image-background.d.ts +32 -0
- package/dist/image-background.js +80 -0
- package/dist/image-background.js.map +1 -0
- package/dist/image.d.ts +79 -0
- package/dist/image.js +155 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/input-accessory-view.d.ts +16 -0
- package/dist/input-accessory-view.js +29 -0
- package/dist/input-accessory-view.js.map +1 -0
- package/dist/keyboard-avoiding-view.d.ts +79 -0
- package/dist/keyboard-avoiding-view.js +172 -0
- package/dist/keyboard-avoiding-view.js.map +1 -0
- package/dist/keyboard-dock.d.ts +126 -0
- package/dist/keyboard-dock.js +327 -0
- package/dist/keyboard-dock.js.map +1 -0
- package/dist/keyboard-taps.d.ts +12 -0
- package/dist/keyboard-taps.js +51 -0
- package/dist/keyboard-taps.js.map +1 -0
- package/dist/modal.d.ts +56 -0
- package/dist/modal.js +102 -0
- package/dist/modal.js.map +1 -0
- package/dist/native-gesture.d.ts +21 -0
- package/dist/native-gesture.js +56 -0
- package/dist/native-gesture.js.map +1 -0
- package/dist/native-ref.d.ts +7 -0
- package/dist/native-ref.js +13 -0
- package/dist/native-ref.js.map +1 -0
- package/dist/pressable.d.ts +220 -0
- package/dist/pressable.js +484 -0
- package/dist/pressable.js.map +1 -0
- package/dist/reanimated.d.ts +19 -0
- package/dist/reanimated.js +111 -0
- package/dist/reanimated.js.map +1 -0
- package/dist/refresh-control.d.ts +50 -0
- package/dist/refresh-control.js +103 -0
- package/dist/refresh-control.js.map +1 -0
- package/dist/safe-area-provider.d.ts +11 -0
- package/dist/safe-area-provider.js +70 -0
- package/dist/safe-area-provider.js.map +1 -0
- package/dist/safe-area-view.d.ts +22 -0
- package/dist/safe-area-view.js +77 -0
- package/dist/safe-area-view.js.map +1 -0
- package/dist/safe-area.d.ts +12 -0
- package/dist/safe-area.js +27 -0
- package/dist/safe-area.js.map +1 -0
- package/dist/scroll-view-props.d.ts +89 -0
- package/dist/scroll-view-props.js +153 -0
- package/dist/scroll-view-props.js.map +1 -0
- package/dist/scroll-view.d.ts +95 -0
- package/dist/scroll-view.js +181 -0
- package/dist/scroll-view.js.map +1 -0
- package/dist/section-list.d.ts +146 -0
- package/dist/section-list.js +300 -0
- package/dist/section-list.js.map +1 -0
- package/dist/sticky-headers.d.ts +41 -0
- package/dist/sticky-headers.js +118 -0
- package/dist/sticky-headers.js.map +1 -0
- package/dist/swipe-refresh-layout.d.ts +51 -0
- package/dist/swipe-refresh-layout.js +162 -0
- package/dist/swipe-refresh-layout.js.map +1 -0
- package/dist/switch.d.ts +54 -0
- package/dist/switch.js +110 -0
- package/dist/switch.js.map +1 -0
- package/dist/template-slot.d.ts +18 -0
- package/dist/template-slot.js +30 -0
- package/dist/template-slot.js.map +1 -0
- package/dist/text-input.d.ts +168 -0
- package/dist/text-input.js +312 -0
- package/dist/text-input.js.map +1 -0
- package/dist/text.d.ts +70 -0
- package/dist/text.js +111 -0
- package/dist/text.js.map +1 -0
- package/dist/touchable-opacity.d.ts +36 -0
- package/dist/touchable-opacity.js +76 -0
- package/dist/touchable-opacity.js.map +1 -0
- package/dist/transforms.d.ts +2 -0
- package/dist/transforms.js +17 -0
- package/dist/transforms.js.map +1 -0
- package/dist/view-base.d.ts +332 -0
- package/dist/view-base.js +534 -0
- package/dist/view-base.js.map +1 -0
- package/dist/view.d.ts +12 -0
- package/dist/view.js +18 -0
- package/dist/view.js.map +1 -0
- package/dist/virtual-list.d.ts +530 -0
- package/dist/virtual-list.js +1150 -0
- package/dist/virtual-list.js.map +1 -0
- package/dist/worklet-scroll.d.ts +13 -0
- package/dist/worklet-scroll.js +49 -0
- package/dist/worklet-scroll.js.map +1 -0
- package/dist/worklet-style.d.ts +13 -0
- package/dist/worklet-style.js +47 -0
- package/dist/worklet-style.js.map +1 -0
- package/dist/worklets.d.ts +89 -0
- package/dist/worklets.js +42 -0
- package/dist/worklets.js.map +1 -0
- package/dist/written-props.d.ts +6 -0
- package/dist/written-props.js +180 -0
- package/dist/written-props.js.map +1 -0
- package/package.json +88 -3
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { type SimpleChanges } from '@angular/core';
|
|
2
|
+
import type { NativeSyntheticEvent } from '@ng-native/fabric';
|
|
3
|
+
import type { TextInputChangePayload } from './events.ts';
|
|
4
|
+
import { ViewBase } from './view-base.ts';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export type KeyboardType = 'default' | 'number-pad' | 'decimal-pad' | 'numeric' | 'email-address' | 'phone-pad' | 'url' | 'ascii-capable' | 'numbers-and-punctuation' | 'name-phone-pad' | 'twitter' | 'web-search' | 'visible-password';
|
|
7
|
+
export type ReturnKeyType = 'done' | 'go' | 'next' | 'search' | 'send' | 'none' | 'previous' | 'default' | 'emergency-call' | 'google' | 'join' | 'route' | 'yahoo';
|
|
8
|
+
export type SubmitBehavior = 'submit' | 'blurAndSubmit' | 'newline';
|
|
9
|
+
/**
|
|
10
|
+
* A text field, wired for signal forms. Commits as `TextInput`, single or multi line by prop.
|
|
11
|
+
*
|
|
12
|
+
* `value` is a `model()`, which is all `FormValueControl<string>` requires, so binding it into a
|
|
13
|
+
* form is `<text-input [formField]="f.name" />` with no adapter class. The rest of the contract is
|
|
14
|
+
* declared too, because Signal Forms only writes to inputs of those names: `disabled` and
|
|
15
|
+
* `readonly` turn `editable` off, `invalid` and `touched` come out as `data-invalid` and
|
|
16
|
+
* `data-touched` for a stylesheet, and `touch` fires from the native blur - there is no DOM one
|
|
17
|
+
* for the form to hear instead. `(changeText)` carries
|
|
18
|
+
* the new string alone, as RN's `onChangeText` does; the raw `(change)`, `(focus)`, `(blur)`,
|
|
19
|
+
* `(submitEditing)`, `(endEditing)`, `(selectionChange)`, `(keyPress)`, `(contentSizeChange)`
|
|
20
|
+
* and `(scroll)` are element events typed in `events.ts`.
|
|
21
|
+
*
|
|
22
|
+
* The interesting part is the echo. A native text field owns state the user is actively
|
|
23
|
+
* changing, so JS and native disagree constantly. RN's protocol: native reports an `eventCount`
|
|
24
|
+
* with every change, JS passes the most recent one back as a prop, and native ignores a `text`
|
|
25
|
+
* update whose count is stale, meaning the user has typed since. Without it, a controlled input
|
|
26
|
+
* fights the cursor and drops characters under fast typing.
|
|
27
|
+
*
|
|
28
|
+
* The other direction is native holding text the app does not: a value set from code after the
|
|
29
|
+
* user has typed, or a keystroke the app refused or rewrote. It is controlled as RN's field is -
|
|
30
|
+
* bind `value` and the app's value is what the field shows - so once each pass has rendered, the
|
|
31
|
+
* field compares the model with the text native last reported and sends the difference as the
|
|
32
|
+
* `setTextAndSelection` command. See `ControlledModel` for how a refusal reaches the model.
|
|
33
|
+
* A value set that way is also measured again, since Fabric sizes the field from native state
|
|
34
|
+
* that takes the new text only after measuring it: a composer cleared after sending shrinks.
|
|
35
|
+
*/
|
|
36
|
+
export declare class TextInput extends ViewBase {
|
|
37
|
+
readonly value: import("@angular/core").ModelSignal<string>;
|
|
38
|
+
/** The new text alone, on every native change. */
|
|
39
|
+
readonly changeText: import("@angular/core").OutputEmitterRef<string>;
|
|
40
|
+
/** Focus left the field. What Signal Forms marks a field touched from. */
|
|
41
|
+
readonly touch: import("@angular/core").OutputEmitterRef<void>;
|
|
42
|
+
/** Refuse input and announce as disabled. Wins over `editable`. */
|
|
43
|
+
readonly disabled: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
44
|
+
/** Refuse input, though still announced as enabled. Wins over `editable`. */
|
|
45
|
+
readonly readonly: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
46
|
+
/** Published as `data-invalid`; nothing native reads it. */
|
|
47
|
+
readonly invalid: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
48
|
+
/** Published as `data-touched`; nothing native reads it. */
|
|
49
|
+
readonly touched: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
50
|
+
/** Allow more than one line. */
|
|
51
|
+
readonly multiline: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
52
|
+
/** iOS: whether a multiline field scrolls its text; off, it grows with it instead. */
|
|
53
|
+
readonly scrollEnabled: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
54
|
+
/** Set to false to make the field read-only. */
|
|
55
|
+
readonly editable: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
56
|
+
/** Shown while the field is empty. */
|
|
57
|
+
readonly placeholder: import("@angular/core").InputSignal<string | undefined>;
|
|
58
|
+
readonly placeholderTextColor: import("@angular/core").InputSignal<string | undefined>;
|
|
59
|
+
/** Which keyboard to show. */
|
|
60
|
+
readonly keyboardType: import("@angular/core").InputSignal<KeyboardType | undefined>;
|
|
61
|
+
/** The label on the return key. */
|
|
62
|
+
readonly returnKeyType: import("@angular/core").InputSignal<ReturnKeyType | undefined>;
|
|
63
|
+
/** What return does. Defaults to `blurAndSubmit` on one line and `newline` on many. */
|
|
64
|
+
readonly submitBehavior: import("@angular/core").InputSignal<SubmitBehavior | undefined>;
|
|
65
|
+
/** Hide what is typed, for passwords. */
|
|
66
|
+
readonly secureTextEntry: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
67
|
+
/** When the keyboard capitalises. Defaults to `sentences`. */
|
|
68
|
+
readonly autoCapitalize: import("@angular/core").InputSignal<"none" | "sentences" | "words" | "characters" | undefined>;
|
|
69
|
+
/** Auto-correct while typing. Defaults to true. */
|
|
70
|
+
readonly autoCorrect: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
71
|
+
/** Focus the field as soon as it mounts. */
|
|
72
|
+
readonly autoFocus: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
73
|
+
/** The most characters allowed, enforced natively so nothing flickers. */
|
|
74
|
+
readonly maxLength: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
|
|
75
|
+
/** Android: the height of a multiline field, in lines. */
|
|
76
|
+
readonly numberOfLines: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
|
|
77
|
+
/** The selected range, or the caret when `start` equals `end`. */
|
|
78
|
+
readonly selection: import("@angular/core").InputSignal<{
|
|
79
|
+
readonly start: number;
|
|
80
|
+
readonly end?: number;
|
|
81
|
+
} | undefined>;
|
|
82
|
+
readonly selectionColor: import("@angular/core").InputSignal<string | undefined>;
|
|
83
|
+
/** Select everything on focus. */
|
|
84
|
+
readonly selectTextOnFocus: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
85
|
+
readonly caretHidden: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
86
|
+
/** Disable the copy, paste and share menu. */
|
|
87
|
+
readonly contextMenuHidden: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
88
|
+
readonly textAlign: import("@angular/core").InputSignal<"left" | "right" | "center" | undefined>;
|
|
89
|
+
readonly allowFontScaling: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
90
|
+
readonly maxFontSizeMultiplier: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
|
|
91
|
+
/** iOS: the `nativeID` of an `<input-accessory-view>` to dock above the keyboard. */
|
|
92
|
+
readonly inputAccessoryViewID: import("@angular/core").InputSignal<string | undefined>;
|
|
93
|
+
/** iOS: when the clear button shows. */
|
|
94
|
+
readonly clearButtonMode: import("@angular/core").InputSignal<"never" | "while-editing" | "unless-editing" | "always" | undefined>;
|
|
95
|
+
/** iOS: empty the field on focus. */
|
|
96
|
+
readonly clearTextOnFocus: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
97
|
+
/** iOS: disable the return key while the field is empty. */
|
|
98
|
+
readonly enablesReturnKeyAutomatically: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
99
|
+
/** iOS: the keyboard's colour scheme. */
|
|
100
|
+
readonly keyboardAppearance: import("@angular/core").InputSignal<"default" | "light" | "dark" | undefined>;
|
|
101
|
+
/** iOS: rules for a generated password, in Apple's Password Rules syntax. */
|
|
102
|
+
readonly passwordRules: import("@angular/core").InputSignal<string | undefined>;
|
|
103
|
+
/** iOS: underline misspellings. Follows `autoCorrect` by default. */
|
|
104
|
+
readonly spellCheck: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
105
|
+
/** iOS: add and remove spaces around pasted and deleted words. */
|
|
106
|
+
readonly smartInsertDelete: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
107
|
+
/** iOS, multiline: turn phone numbers, links and addresses into taps. */
|
|
108
|
+
readonly dataDetectorTypes: import("@angular/core").InputSignal<string | readonly string[] | undefined>;
|
|
109
|
+
/** iOS: what the field holds, so the system can autofill it. */
|
|
110
|
+
readonly textContentType: import("@angular/core").InputSignal<string | undefined>;
|
|
111
|
+
/** Android: the autofill hint. */
|
|
112
|
+
readonly autoComplete: import("@angular/core").InputSignal<string | undefined>;
|
|
113
|
+
/**
|
|
114
|
+
* Android: the underline colour, transparent by default.
|
|
115
|
+
*
|
|
116
|
+
* Not a taste call. Android's `EditText` carries the platform's own underline in its background
|
|
117
|
+
* drawable, so a field with a border of its own draws two: the app's box, and a grey line
|
|
118
|
+
* through it that turns blue on focus. React Native's `TextInput` defaults this prop to
|
|
119
|
+
* `'transparent'` for exactly that reason, and this is that default rather than a new opinion.
|
|
120
|
+
* Ignored on iOS, where the native field has no such chrome.
|
|
121
|
+
*/
|
|
122
|
+
readonly underlineColorAndroid: import("@angular/core").InputSignal<string>;
|
|
123
|
+
/** Android: the caret colour. */
|
|
124
|
+
readonly cursorColor: import("@angular/core").InputSignal<string | undefined>;
|
|
125
|
+
/** Android: the selection handle colour. */
|
|
126
|
+
readonly selectionHandleColor: import("@angular/core").InputSignal<string | undefined>;
|
|
127
|
+
/** Android: where text sits in a tall field. */
|
|
128
|
+
readonly textAlignVertical: import("@angular/core").InputSignal<"auto" | "center" | "top" | "bottom" | undefined>;
|
|
129
|
+
/** Android: whether autofill may fill this field. */
|
|
130
|
+
readonly importantForAutofill: import("@angular/core").InputSignal<"auto" | "yes" | "no" | "noExcludeDescendants" | "yesExcludeDescendants" | undefined>;
|
|
131
|
+
/** Android: set to false to focus without raising the keyboard. */
|
|
132
|
+
readonly showSoftInputOnFocus: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
133
|
+
/** Android: keep the field in place in landscape rather than going full screen. */
|
|
134
|
+
readonly disableFullscreenUI: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
|
|
135
|
+
/** Android: a drawable resource shown at the left of the field. */
|
|
136
|
+
readonly inlineImageLeft: import("@angular/core").InputSignal<string | undefined>;
|
|
137
|
+
readonly inlineImagePadding: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
|
|
138
|
+
/** Android: the line-breaking strategy. */
|
|
139
|
+
readonly textBreakStrategy: import("@angular/core").InputSignal<"simple" | "highQuality" | "balanced" | undefined>;
|
|
140
|
+
protected readonly eventCount: import("@angular/core").WritableSignal<number>;
|
|
141
|
+
protected readonly resolvedEditable: import("@angular/core").Signal<boolean | undefined>;
|
|
142
|
+
protected disabledForAccessibility(): boolean | undefined;
|
|
143
|
+
protected readonly resolvedSubmitBehavior: import("@angular/core").Signal<SubmitBehavior>;
|
|
144
|
+
private readonly keyboard;
|
|
145
|
+
/** What native last reported, so a value set from code can be told from an echo. */
|
|
146
|
+
private lastNativeText;
|
|
147
|
+
private readonly control;
|
|
148
|
+
constructor();
|
|
149
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
150
|
+
/**
|
|
151
|
+
* With the keyboard already up, keep the field clear of it. UIKit scrolls a field clear as the
|
|
152
|
+
* keyboard rises, not when focus moves from one field to another beneath it, which is what a
|
|
153
|
+
* form's Next key does; native form screens keep the new field on screen either way.
|
|
154
|
+
*/
|
|
155
|
+
protected onFocus(): void;
|
|
156
|
+
/** Bring the keyboard up on this field. A view command, so it reaches native directly. */
|
|
157
|
+
focus(): void;
|
|
158
|
+
blur(): void;
|
|
159
|
+
/** Empty the field. */
|
|
160
|
+
clear(): void;
|
|
161
|
+
/** Move the caret, or select a range. */
|
|
162
|
+
setSelection(start: number, end?: number): void;
|
|
163
|
+
/** Whether this field currently has the keyboard. */
|
|
164
|
+
isFocused(): boolean;
|
|
165
|
+
protected onNativeChange(event: NativeSyntheticEvent<Partial<TextInputChangePayload>>): void;
|
|
166
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TextInput, never>;
|
|
167
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<TextInput, "text-input", ["textInput"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "multiline": { "alias": "multiline"; "required": false; "isSignal": true; }; "scrollEnabled": { "alias": "scrollEnabled"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "placeholderTextColor": { "alias": "placeholderTextColor"; "required": false; "isSignal": true; }; "keyboardType": { "alias": "keyboardType"; "required": false; "isSignal": true; }; "returnKeyType": { "alias": "returnKeyType"; "required": false; "isSignal": true; }; "submitBehavior": { "alias": "submitBehavior"; "required": false; "isSignal": true; }; "secureTextEntry": { "alias": "secureTextEntry"; "required": false; "isSignal": true; }; "autoCapitalize": { "alias": "autoCapitalize"; "required": false; "isSignal": true; }; "autoCorrect": { "alias": "autoCorrect"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; "numberOfLines": { "alias": "numberOfLines"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "selectionColor": { "alias": "selectionColor"; "required": false; "isSignal": true; }; "selectTextOnFocus": { "alias": "selectTextOnFocus"; "required": false; "isSignal": true; }; "caretHidden": { "alias": "caretHidden"; "required": false; "isSignal": true; }; "contextMenuHidden": { "alias": "contextMenuHidden"; "required": false; "isSignal": true; }; "textAlign": { "alias": "textAlign"; "required": false; "isSignal": true; }; "allowFontScaling": { "alias": "allowFontScaling"; "required": false; "isSignal": true; }; "maxFontSizeMultiplier": { "alias": "maxFontSizeMultiplier"; "required": false; "isSignal": true; }; "inputAccessoryViewID": { "alias": "inputAccessoryViewID"; "required": false; "isSignal": true; }; "clearButtonMode": { "alias": "clearButtonMode"; "required": false; "isSignal": true; }; "clearTextOnFocus": { "alias": "clearTextOnFocus"; "required": false; "isSignal": true; }; "enablesReturnKeyAutomatically": { "alias": "enablesReturnKeyAutomatically"; "required": false; "isSignal": true; }; "keyboardAppearance": { "alias": "keyboardAppearance"; "required": false; "isSignal": true; }; "passwordRules": { "alias": "passwordRules"; "required": false; "isSignal": true; }; "spellCheck": { "alias": "spellCheck"; "required": false; "isSignal": true; }; "smartInsertDelete": { "alias": "smartInsertDelete"; "required": false; "isSignal": true; }; "dataDetectorTypes": { "alias": "dataDetectorTypes"; "required": false; "isSignal": true; }; "textContentType": { "alias": "textContentType"; "required": false; "isSignal": true; }; "autoComplete": { "alias": "autoComplete"; "required": false; "isSignal": true; }; "underlineColorAndroid": { "alias": "underlineColorAndroid"; "required": false; "isSignal": true; }; "cursorColor": { "alias": "cursorColor"; "required": false; "isSignal": true; }; "selectionHandleColor": { "alias": "selectionHandleColor"; "required": false; "isSignal": true; }; "textAlignVertical": { "alias": "textAlignVertical"; "required": false; "isSignal": true; }; "importantForAutofill": { "alias": "importantForAutofill"; "required": false; "isSignal": true; }; "showSoftInputOnFocus": { "alias": "showSoftInputOnFocus"; "required": false; "isSignal": true; }; "disableFullscreenUI": { "alias": "disableFullscreenUI"; "required": false; "isSignal": true; }; "inlineImageLeft": { "alias": "inlineImageLeft"; "required": false; "isSignal": true; }; "inlineImagePadding": { "alias": "inlineImagePadding"; "required": false; "isSignal": true; }; "textBreakStrategy": { "alias": "textBreakStrategy"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "changeText": "changeText"; "touch": "touch"; }, never, never, true, never>;
|
|
168
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { Directive, afterRenderEffect, booleanAttribute, computed, inject, input, model, output, signal, } from '@angular/core';
|
|
2
|
+
import { Keyboard } from '@ng-native/device';
|
|
3
|
+
import { ControlledModel } from "./controlled-model.js";
|
|
4
|
+
import { optionalBoolean, optionalNumber } from "./transforms.js";
|
|
5
|
+
import { ViewBase } from "./view-base.js";
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/**
|
|
8
|
+
* A text field, wired for signal forms. Commits as `TextInput`, single or multi line by prop.
|
|
9
|
+
*
|
|
10
|
+
* `value` is a `model()`, which is all `FormValueControl<string>` requires, so binding it into a
|
|
11
|
+
* form is `<text-input [formField]="f.name" />` with no adapter class. The rest of the contract is
|
|
12
|
+
* declared too, because Signal Forms only writes to inputs of those names: `disabled` and
|
|
13
|
+
* `readonly` turn `editable` off, `invalid` and `touched` come out as `data-invalid` and
|
|
14
|
+
* `data-touched` for a stylesheet, and `touch` fires from the native blur - there is no DOM one
|
|
15
|
+
* for the form to hear instead. `(changeText)` carries
|
|
16
|
+
* the new string alone, as RN's `onChangeText` does; the raw `(change)`, `(focus)`, `(blur)`,
|
|
17
|
+
* `(submitEditing)`, `(endEditing)`, `(selectionChange)`, `(keyPress)`, `(contentSizeChange)`
|
|
18
|
+
* and `(scroll)` are element events typed in `events.ts`.
|
|
19
|
+
*
|
|
20
|
+
* The interesting part is the echo. A native text field owns state the user is actively
|
|
21
|
+
* changing, so JS and native disagree constantly. RN's protocol: native reports an `eventCount`
|
|
22
|
+
* with every change, JS passes the most recent one back as a prop, and native ignores a `text`
|
|
23
|
+
* update whose count is stale, meaning the user has typed since. Without it, a controlled input
|
|
24
|
+
* fights the cursor and drops characters under fast typing.
|
|
25
|
+
*
|
|
26
|
+
* The other direction is native holding text the app does not: a value set from code after the
|
|
27
|
+
* user has typed, or a keystroke the app refused or rewrote. It is controlled as RN's field is -
|
|
28
|
+
* bind `value` and the app's value is what the field shows - so once each pass has rendered, the
|
|
29
|
+
* field compares the model with the text native last reported and sends the difference as the
|
|
30
|
+
* `setTextAndSelection` command. See `ControlledModel` for how a refusal reaches the model.
|
|
31
|
+
* A value set that way is also measured again, since Fabric sizes the field from native state
|
|
32
|
+
* that takes the new text only after measuring it: a composer cleared after sending shrinks.
|
|
33
|
+
*/
|
|
34
|
+
export class TextInput extends ViewBase {
|
|
35
|
+
value = model('', /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
37
|
+
/** The new text alone, on every native change. */
|
|
38
|
+
changeText = output();
|
|
39
|
+
/** Focus left the field. What Signal Forms marks a field touched from. */
|
|
40
|
+
touch = output();
|
|
41
|
+
/** Refuse input and announce as disabled. Wins over `editable`. */
|
|
42
|
+
disabled = input(undefined, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
43
|
+
/** Refuse input, though still announced as enabled. Wins over `editable`. */
|
|
44
|
+
readonly = input(undefined, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
45
|
+
/** Published as `data-invalid`; nothing native reads it. */
|
|
46
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
47
|
+
/** Published as `data-touched`; nothing native reads it. */
|
|
48
|
+
touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
49
|
+
/** Allow more than one line. */
|
|
50
|
+
multiline = input(undefined, { ...(ngDevMode ? { debugName: "multiline" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
51
|
+
/** iOS: whether a multiline field scrolls its text; off, it grows with it instead. */
|
|
52
|
+
scrollEnabled = input(undefined, { ...(ngDevMode ? { debugName: "scrollEnabled" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
53
|
+
/** Set to false to make the field read-only. */
|
|
54
|
+
editable = input(undefined, { ...(ngDevMode ? { debugName: "editable" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
55
|
+
/** Shown while the field is empty. */
|
|
56
|
+
placeholder = input(/* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
58
|
+
placeholderTextColor = input(/* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [undefined, { debugName: "placeholderTextColor" }] : /* istanbul ignore next */ []));
|
|
60
|
+
/** Which keyboard to show. */
|
|
61
|
+
keyboardType = input(/* @ts-ignore */
|
|
62
|
+
...(ngDevMode ? [undefined, { debugName: "keyboardType" }] : /* istanbul ignore next */ []));
|
|
63
|
+
/** The label on the return key. */
|
|
64
|
+
returnKeyType = input(/* @ts-ignore */
|
|
65
|
+
...(ngDevMode ? [undefined, { debugName: "returnKeyType" }] : /* istanbul ignore next */ []));
|
|
66
|
+
/** What return does. Defaults to `blurAndSubmit` on one line and `newline` on many. */
|
|
67
|
+
submitBehavior = input(/* @ts-ignore */
|
|
68
|
+
...(ngDevMode ? [undefined, { debugName: "submitBehavior" }] : /* istanbul ignore next */ []));
|
|
69
|
+
/** Hide what is typed, for passwords. */
|
|
70
|
+
secureTextEntry = input(undefined, { ...(ngDevMode ? { debugName: "secureTextEntry" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
71
|
+
/** When the keyboard capitalises. Defaults to `sentences`. */
|
|
72
|
+
autoCapitalize = input(/* @ts-ignore */
|
|
73
|
+
...(ngDevMode ? [undefined, { debugName: "autoCapitalize" }] : /* istanbul ignore next */ []));
|
|
74
|
+
/** Auto-correct while typing. Defaults to true. */
|
|
75
|
+
autoCorrect = input(undefined, { ...(ngDevMode ? { debugName: "autoCorrect" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
76
|
+
/** Focus the field as soon as it mounts. */
|
|
77
|
+
autoFocus = input(undefined, { ...(ngDevMode ? { debugName: "autoFocus" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
78
|
+
/** The most characters allowed, enforced natively so nothing flickers. */
|
|
79
|
+
maxLength = input(undefined, { ...(ngDevMode ? { debugName: "maxLength" } : /* istanbul ignore next */ {}), transform: optionalNumber });
|
|
80
|
+
/** Android: the height of a multiline field, in lines. */
|
|
81
|
+
numberOfLines = input(undefined, { ...(ngDevMode ? { debugName: "numberOfLines" } : /* istanbul ignore next */ {}), transform: optionalNumber });
|
|
82
|
+
/** The selected range, or the caret when `start` equals `end`. */
|
|
83
|
+
selection = input(/* @ts-ignore */
|
|
84
|
+
...(ngDevMode ? [undefined, { debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
85
|
+
selectionColor = input(/* @ts-ignore */
|
|
86
|
+
...(ngDevMode ? [undefined, { debugName: "selectionColor" }] : /* istanbul ignore next */ []));
|
|
87
|
+
/** Select everything on focus. */
|
|
88
|
+
selectTextOnFocus = input(undefined, { ...(ngDevMode ? { debugName: "selectTextOnFocus" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
89
|
+
caretHidden = input(undefined, { ...(ngDevMode ? { debugName: "caretHidden" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
90
|
+
/** Disable the copy, paste and share menu. */
|
|
91
|
+
contextMenuHidden = input(undefined, { ...(ngDevMode ? { debugName: "contextMenuHidden" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
92
|
+
textAlign = input(/* @ts-ignore */
|
|
93
|
+
...(ngDevMode ? [undefined, { debugName: "textAlign" }] : /* istanbul ignore next */ []));
|
|
94
|
+
allowFontScaling = input(undefined, { ...(ngDevMode ? { debugName: "allowFontScaling" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
95
|
+
maxFontSizeMultiplier = input(undefined, { ...(ngDevMode ? { debugName: "maxFontSizeMultiplier" } : /* istanbul ignore next */ {}), transform: optionalNumber });
|
|
96
|
+
/** iOS: the `nativeID` of an `<input-accessory-view>` to dock above the keyboard. */
|
|
97
|
+
inputAccessoryViewID = input(/* @ts-ignore */
|
|
98
|
+
...(ngDevMode ? [undefined, { debugName: "inputAccessoryViewID" }] : /* istanbul ignore next */ []));
|
|
99
|
+
/** iOS: when the clear button shows. */
|
|
100
|
+
clearButtonMode = input(/* @ts-ignore */
|
|
101
|
+
...(ngDevMode ? [undefined, { debugName: "clearButtonMode" }] : /* istanbul ignore next */ []));
|
|
102
|
+
/** iOS: empty the field on focus. */
|
|
103
|
+
clearTextOnFocus = input(undefined, { ...(ngDevMode ? { debugName: "clearTextOnFocus" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
104
|
+
/** iOS: disable the return key while the field is empty. */
|
|
105
|
+
enablesReturnKeyAutomatically = input(undefined, { ...(ngDevMode ? { debugName: "enablesReturnKeyAutomatically" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
106
|
+
/** iOS: the keyboard's colour scheme. */
|
|
107
|
+
keyboardAppearance = input(/* @ts-ignore */
|
|
108
|
+
...(ngDevMode ? [undefined, { debugName: "keyboardAppearance" }] : /* istanbul ignore next */ []));
|
|
109
|
+
/** iOS: rules for a generated password, in Apple's Password Rules syntax. */
|
|
110
|
+
passwordRules = input(/* @ts-ignore */
|
|
111
|
+
...(ngDevMode ? [undefined, { debugName: "passwordRules" }] : /* istanbul ignore next */ []));
|
|
112
|
+
/** iOS: underline misspellings. Follows `autoCorrect` by default. */
|
|
113
|
+
spellCheck = input(undefined, { ...(ngDevMode ? { debugName: "spellCheck" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
114
|
+
/** iOS: add and remove spaces around pasted and deleted words. */
|
|
115
|
+
smartInsertDelete = input(undefined, { ...(ngDevMode ? { debugName: "smartInsertDelete" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
116
|
+
/** iOS, multiline: turn phone numbers, links and addresses into taps. */
|
|
117
|
+
dataDetectorTypes = input(/* @ts-ignore */
|
|
118
|
+
...(ngDevMode ? [undefined, { debugName: "dataDetectorTypes" }] : /* istanbul ignore next */ []));
|
|
119
|
+
/** iOS: what the field holds, so the system can autofill it. */
|
|
120
|
+
textContentType = input(/* @ts-ignore */
|
|
121
|
+
...(ngDevMode ? [undefined, { debugName: "textContentType" }] : /* istanbul ignore next */ []));
|
|
122
|
+
/** Android: the autofill hint. */
|
|
123
|
+
autoComplete = input(/* @ts-ignore */
|
|
124
|
+
...(ngDevMode ? [undefined, { debugName: "autoComplete" }] : /* istanbul ignore next */ []));
|
|
125
|
+
/**
|
|
126
|
+
* Android: the underline colour, transparent by default.
|
|
127
|
+
*
|
|
128
|
+
* Not a taste call. Android's `EditText` carries the platform's own underline in its background
|
|
129
|
+
* drawable, so a field with a border of its own draws two: the app's box, and a grey line
|
|
130
|
+
* through it that turns blue on focus. React Native's `TextInput` defaults this prop to
|
|
131
|
+
* `'transparent'` for exactly that reason, and this is that default rather than a new opinion.
|
|
132
|
+
* Ignored on iOS, where the native field has no such chrome.
|
|
133
|
+
*/
|
|
134
|
+
underlineColorAndroid = input('transparent', /* @ts-ignore */
|
|
135
|
+
...(ngDevMode ? [{ debugName: "underlineColorAndroid" }] : /* istanbul ignore next */ []));
|
|
136
|
+
/** Android: the caret colour. */
|
|
137
|
+
cursorColor = input(/* @ts-ignore */
|
|
138
|
+
...(ngDevMode ? [undefined, { debugName: "cursorColor" }] : /* istanbul ignore next */ []));
|
|
139
|
+
/** Android: the selection handle colour. */
|
|
140
|
+
selectionHandleColor = input(/* @ts-ignore */
|
|
141
|
+
...(ngDevMode ? [undefined, { debugName: "selectionHandleColor" }] : /* istanbul ignore next */ []));
|
|
142
|
+
/** Android: where text sits in a tall field. */
|
|
143
|
+
textAlignVertical = input(/* @ts-ignore */
|
|
144
|
+
...(ngDevMode ? [undefined, { debugName: "textAlignVertical" }] : /* istanbul ignore next */ []));
|
|
145
|
+
/** Android: whether autofill may fill this field. */
|
|
146
|
+
importantForAutofill = input(/* @ts-ignore */
|
|
147
|
+
...(ngDevMode ? [undefined, { debugName: "importantForAutofill" }] : /* istanbul ignore next */ []));
|
|
148
|
+
/** Android: set to false to focus without raising the keyboard. */
|
|
149
|
+
showSoftInputOnFocus = input(undefined, { ...(ngDevMode ? { debugName: "showSoftInputOnFocus" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
150
|
+
/** Android: keep the field in place in landscape rather than going full screen. */
|
|
151
|
+
disableFullscreenUI = input(undefined, { ...(ngDevMode ? { debugName: "disableFullscreenUI" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
|
|
152
|
+
/** Android: a drawable resource shown at the left of the field. */
|
|
153
|
+
inlineImageLeft = input(/* @ts-ignore */
|
|
154
|
+
...(ngDevMode ? [undefined, { debugName: "inlineImageLeft" }] : /* istanbul ignore next */ []));
|
|
155
|
+
inlineImagePadding = input(undefined, { ...(ngDevMode ? { debugName: "inlineImagePadding" } : /* istanbul ignore next */ {}), transform: optionalNumber });
|
|
156
|
+
/** Android: the line-breaking strategy. */
|
|
157
|
+
textBreakStrategy = input(/* @ts-ignore */
|
|
158
|
+
...(ngDevMode ? [undefined, { debugName: "textBreakStrategy" }] : /* istanbul ignore next */ []));
|
|
159
|
+
eventCount = signal(0, /* @ts-ignore */
|
|
160
|
+
...(ngDevMode ? [{ debugName: "eventCount" }] : /* istanbul ignore next */ []));
|
|
161
|
+
resolvedEditable = computed(() => this.disabled() || this.readonly() ? false : this.editable(), /* @ts-ignore */
|
|
162
|
+
...(ngDevMode ? [{ debugName: "resolvedEditable" }] : /* istanbul ignore next */ []));
|
|
163
|
+
disabledForAccessibility() {
|
|
164
|
+
return this.disabled();
|
|
165
|
+
}
|
|
166
|
+
resolvedSubmitBehavior = computed(() => {
|
|
167
|
+
const explicit = this.submitBehavior();
|
|
168
|
+
// A single-line field has no line to add, so `newline` collapses to the default.
|
|
169
|
+
if (explicit && (this.multiline() || explicit !== 'newline'))
|
|
170
|
+
return explicit;
|
|
171
|
+
return this.multiline() ? 'newline' : 'blurAndSubmit';
|
|
172
|
+
}, /* @ts-ignore */
|
|
173
|
+
...(ngDevMode ? [{ debugName: "resolvedSubmitBehavior" }] : /* istanbul ignore next */ []));
|
|
174
|
+
keyboard = inject(Keyboard);
|
|
175
|
+
/** What native last reported, so a value set from code can be told from an echo. */
|
|
176
|
+
lastNativeText = null;
|
|
177
|
+
control = new ControlledModel(this.value, 'value');
|
|
178
|
+
constructor() {
|
|
179
|
+
super();
|
|
180
|
+
// RN's layout effect, keyed as RN keys it: the value, and the count every native change
|
|
181
|
+
// moves on, so a refusal that leaves the value where it was is compared all the same. After
|
|
182
|
+
// render rather than as an ordinary effect, because an accepted edit only reaches the model
|
|
183
|
+
// during change detection, and comparing before it has would send the old text back.
|
|
184
|
+
afterRenderEffect({
|
|
185
|
+
write: () => {
|
|
186
|
+
const desired = this.value();
|
|
187
|
+
const count = this.eventCount();
|
|
188
|
+
if (this.lastNativeText === null || this.lastNativeText === desired)
|
|
189
|
+
return;
|
|
190
|
+
// The `text` prop alone may be ignored as stale, so send it as a command with the count
|
|
191
|
+
// native expects.
|
|
192
|
+
this.lastNativeText = desired;
|
|
193
|
+
this.engine.dispatchCommand(this.node, 'setTextAndSelection', [count, desired, -1, -1]);
|
|
194
|
+
// Fabric sized the field for the text it had; see `HostEngine.remeasure`.
|
|
195
|
+
this.engine.remeasure(this.node);
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
ngOnChanges(changes) {
|
|
200
|
+
super.ngOnChanges(changes);
|
|
201
|
+
this.control.noteChanges(changes);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* With the keyboard already up, keep the field clear of it. UIKit scrolls a field clear as the
|
|
205
|
+
* keyboard rises, not when focus moves from one field to another beneath it, which is what a
|
|
206
|
+
* form's Next key does; native form screens keep the new field on screen either way.
|
|
207
|
+
*/
|
|
208
|
+
onFocus() {
|
|
209
|
+
const { height, screenY } = this.keyboard.metrics();
|
|
210
|
+
if (height > 0 && screenY !== undefined)
|
|
211
|
+
this.engine.reveal(this.node, { visibleBottom: screenY });
|
|
212
|
+
}
|
|
213
|
+
/** Bring the keyboard up on this field. A view command, so it reaches native directly. */
|
|
214
|
+
focus() {
|
|
215
|
+
this.engine.dispatchCommand(this.node, 'focus');
|
|
216
|
+
}
|
|
217
|
+
blur() {
|
|
218
|
+
this.engine.dispatchCommand(this.node, 'blur');
|
|
219
|
+
}
|
|
220
|
+
/** Empty the field. */
|
|
221
|
+
clear() {
|
|
222
|
+
this.value.set('');
|
|
223
|
+
}
|
|
224
|
+
/** Move the caret, or select a range. */
|
|
225
|
+
setSelection(start, end = start) {
|
|
226
|
+
this.engine.dispatchCommand(this.node, 'setTextAndSelection', [
|
|
227
|
+
this.eventCount(),
|
|
228
|
+
null,
|
|
229
|
+
start,
|
|
230
|
+
end,
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
/** Whether this field currently has the keyboard. */
|
|
234
|
+
isFocused() {
|
|
235
|
+
return this.engine.focused === this.node;
|
|
236
|
+
}
|
|
237
|
+
onNativeChange(event) {
|
|
238
|
+
const native = event.nativeEvent;
|
|
239
|
+
const text = native?.text ?? '';
|
|
240
|
+
// Order matters, as it does in RN: the value first, the count last.
|
|
241
|
+
this.lastNativeText = text;
|
|
242
|
+
this.control.propose(text);
|
|
243
|
+
this.eventCount.set(native?.eventCount ?? this.eventCount() + 1);
|
|
244
|
+
this.changeText.emit(text);
|
|
245
|
+
}
|
|
246
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: TextInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
247
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.2.0", type: TextInput, isStandalone: true, selector: "text-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, scrollEnabled: { classPropertyName: "scrollEnabled", publicName: "scrollEnabled", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, placeholderTextColor: { classPropertyName: "placeholderTextColor", publicName: "placeholderTextColor", isSignal: true, isRequired: false, transformFunction: null }, keyboardType: { classPropertyName: "keyboardType", publicName: "keyboardType", isSignal: true, isRequired: false, transformFunction: null }, returnKeyType: { classPropertyName: "returnKeyType", publicName: "returnKeyType", isSignal: true, isRequired: false, transformFunction: null }, submitBehavior: { classPropertyName: "submitBehavior", publicName: "submitBehavior", isSignal: true, isRequired: false, transformFunction: null }, secureTextEntry: { classPropertyName: "secureTextEntry", publicName: "secureTextEntry", isSignal: true, isRequired: false, transformFunction: null }, autoCapitalize: { classPropertyName: "autoCapitalize", publicName: "autoCapitalize", isSignal: true, isRequired: false, transformFunction: null }, autoCorrect: { classPropertyName: "autoCorrect", publicName: "autoCorrect", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, numberOfLines: { classPropertyName: "numberOfLines", publicName: "numberOfLines", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, selectionColor: { classPropertyName: "selectionColor", publicName: "selectionColor", isSignal: true, isRequired: false, transformFunction: null }, selectTextOnFocus: { classPropertyName: "selectTextOnFocus", publicName: "selectTextOnFocus", isSignal: true, isRequired: false, transformFunction: null }, caretHidden: { classPropertyName: "caretHidden", publicName: "caretHidden", isSignal: true, isRequired: false, transformFunction: null }, contextMenuHidden: { classPropertyName: "contextMenuHidden", publicName: "contextMenuHidden", isSignal: true, isRequired: false, transformFunction: null }, textAlign: { classPropertyName: "textAlign", publicName: "textAlign", isSignal: true, isRequired: false, transformFunction: null }, allowFontScaling: { classPropertyName: "allowFontScaling", publicName: "allowFontScaling", isSignal: true, isRequired: false, transformFunction: null }, maxFontSizeMultiplier: { classPropertyName: "maxFontSizeMultiplier", publicName: "maxFontSizeMultiplier", isSignal: true, isRequired: false, transformFunction: null }, inputAccessoryViewID: { classPropertyName: "inputAccessoryViewID", publicName: "inputAccessoryViewID", isSignal: true, isRequired: false, transformFunction: null }, clearButtonMode: { classPropertyName: "clearButtonMode", publicName: "clearButtonMode", isSignal: true, isRequired: false, transformFunction: null }, clearTextOnFocus: { classPropertyName: "clearTextOnFocus", publicName: "clearTextOnFocus", isSignal: true, isRequired: false, transformFunction: null }, enablesReturnKeyAutomatically: { classPropertyName: "enablesReturnKeyAutomatically", publicName: "enablesReturnKeyAutomatically", isSignal: true, isRequired: false, transformFunction: null }, keyboardAppearance: { classPropertyName: "keyboardAppearance", publicName: "keyboardAppearance", isSignal: true, isRequired: false, transformFunction: null }, passwordRules: { classPropertyName: "passwordRules", publicName: "passwordRules", isSignal: true, isRequired: false, transformFunction: null }, spellCheck: { classPropertyName: "spellCheck", publicName: "spellCheck", isSignal: true, isRequired: false, transformFunction: null }, smartInsertDelete: { classPropertyName: "smartInsertDelete", publicName: "smartInsertDelete", isSignal: true, isRequired: false, transformFunction: null }, dataDetectorTypes: { classPropertyName: "dataDetectorTypes", publicName: "dataDetectorTypes", isSignal: true, isRequired: false, transformFunction: null }, textContentType: { classPropertyName: "textContentType", publicName: "textContentType", isSignal: true, isRequired: false, transformFunction: null }, autoComplete: { classPropertyName: "autoComplete", publicName: "autoComplete", isSignal: true, isRequired: false, transformFunction: null }, underlineColorAndroid: { classPropertyName: "underlineColorAndroid", publicName: "underlineColorAndroid", isSignal: true, isRequired: false, transformFunction: null }, cursorColor: { classPropertyName: "cursorColor", publicName: "cursorColor", isSignal: true, isRequired: false, transformFunction: null }, selectionHandleColor: { classPropertyName: "selectionHandleColor", publicName: "selectionHandleColor", isSignal: true, isRequired: false, transformFunction: null }, textAlignVertical: { classPropertyName: "textAlignVertical", publicName: "textAlignVertical", isSignal: true, isRequired: false, transformFunction: null }, importantForAutofill: { classPropertyName: "importantForAutofill", publicName: "importantForAutofill", isSignal: true, isRequired: false, transformFunction: null }, showSoftInputOnFocus: { classPropertyName: "showSoftInputOnFocus", publicName: "showSoftInputOnFocus", isSignal: true, isRequired: false, transformFunction: null }, disableFullscreenUI: { classPropertyName: "disableFullscreenUI", publicName: "disableFullscreenUI", isSignal: true, isRequired: false, transformFunction: null }, inlineImageLeft: { classPropertyName: "inlineImageLeft", publicName: "inlineImageLeft", isSignal: true, isRequired: false, transformFunction: null }, inlineImagePadding: { classPropertyName: "inlineImagePadding", publicName: "inlineImagePadding", isSignal: true, isRequired: false, transformFunction: null }, textBreakStrategy: { classPropertyName: "textBreakStrategy", publicName: "textBreakStrategy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changeText: "changeText", touch: "touch" }, host: { listeners: { "blur": "touch.emit()", "focus": "onFocus()", "change": "onNativeChange($event)" }, properties: { "text": "value()", "mostRecentEventCount": "eventCount()", "multiline": "multiline()", "scrollEnabled": "scrollEnabled()", "editable": "resolvedEditable()", "accessibilityState": "accessibilityStateProp()", "attr.data-disabled": "disabled() ? '' : null", "attr.data-invalid": "invalid() ? '' : null", "attr.data-touched": "touched() ? '' : null", "placeholder": "placeholder()", "placeholderTextColor": "placeholderTextColor()", "keyboardType": "keyboardType()", "returnKeyType": "returnKeyType()", "submitBehavior": "resolvedSubmitBehavior()", "secureTextEntry": "secureTextEntry()", "autoCapitalize": "autoCapitalize()", "autoCorrect": "autoCorrect()", "autoFocus": "autoFocus()", "maxLength": "maxLength()", "numberOfLines": "numberOfLines()", "selection": "selection()", "selectionColor": "selectionColor()", "selectTextOnFocus": "selectTextOnFocus()", "caretHidden": "caretHidden()", "contextMenuHidden": "contextMenuHidden()", "textAlign": "textAlign()", "allowFontScaling": "allowFontScaling()", "maxFontSizeMultiplier": "maxFontSizeMultiplier()", "inputAccessoryViewID": "inputAccessoryViewID()", "clearButtonMode": "clearButtonMode()", "clearTextOnFocus": "clearTextOnFocus()", "enablesReturnKeyAutomatically": "enablesReturnKeyAutomatically()", "keyboardAppearance": "keyboardAppearance()", "passwordRules": "passwordRules()", "spellCheck": "spellCheck()", "smartInsertDelete": "smartInsertDelete()", "dataDetectorTypes": "dataDetectorTypes()", "textContentType": "textContentType()", "autoComplete": "autoComplete()", "underlineColorAndroid": "underlineColorAndroid()", "cursorColor": "cursorColor()", "selectionHandleColor": "selectionHandleColor()", "textAlignVertical": "textAlignVertical()", "importantForAutofill": "importantForAutofill()", "showSoftInputOnFocus": "showSoftInputOnFocus()", "disableFullscreenUI": "disableFullscreenUI()", "inlineImageLeft": "inlineImageLeft()", "inlineImagePadding": "inlineImagePadding()", "textBreakStrategy": "textBreakStrategy()" } }, exportAs: ["textInput"], usesInheritance: true, usesOnChanges: true, ngImport: i0 });
|
|
248
|
+
}
|
|
249
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: TextInput, decorators: [{
|
|
250
|
+
type: Directive,
|
|
251
|
+
args: [{
|
|
252
|
+
selector: 'text-input',
|
|
253
|
+
exportAs: 'textInput',
|
|
254
|
+
host: {
|
|
255
|
+
'[text]': 'value()',
|
|
256
|
+
'[mostRecentEventCount]': 'eventCount()',
|
|
257
|
+
'[multiline]': 'multiline()',
|
|
258
|
+
'[scrollEnabled]': 'scrollEnabled()',
|
|
259
|
+
'[editable]': 'resolvedEditable()',
|
|
260
|
+
// `disabled` is an input of ours, so it cannot reach `ngOnChanges` on the base; this is
|
|
261
|
+
// the one binding that keeps the announced state in step with it.
|
|
262
|
+
'[accessibilityState]': 'accessibilityStateProp()',
|
|
263
|
+
'[attr.data-disabled]': "disabled() ? '' : null",
|
|
264
|
+
'[attr.data-invalid]': "invalid() ? '' : null",
|
|
265
|
+
'[attr.data-touched]': "touched() ? '' : null",
|
|
266
|
+
'(blur)': 'touch.emit()',
|
|
267
|
+
'(focus)': 'onFocus()',
|
|
268
|
+
'[placeholder]': 'placeholder()',
|
|
269
|
+
'[placeholderTextColor]': 'placeholderTextColor()',
|
|
270
|
+
'[keyboardType]': 'keyboardType()',
|
|
271
|
+
'[returnKeyType]': 'returnKeyType()',
|
|
272
|
+
'[submitBehavior]': 'resolvedSubmitBehavior()',
|
|
273
|
+
'[secureTextEntry]': 'secureTextEntry()',
|
|
274
|
+
'[autoCapitalize]': 'autoCapitalize()',
|
|
275
|
+
'[autoCorrect]': 'autoCorrect()',
|
|
276
|
+
'[autoFocus]': 'autoFocus()',
|
|
277
|
+
'[maxLength]': 'maxLength()',
|
|
278
|
+
'[numberOfLines]': 'numberOfLines()',
|
|
279
|
+
'[selection]': 'selection()',
|
|
280
|
+
'[selectionColor]': 'selectionColor()',
|
|
281
|
+
'[selectTextOnFocus]': 'selectTextOnFocus()',
|
|
282
|
+
'[caretHidden]': 'caretHidden()',
|
|
283
|
+
'[contextMenuHidden]': 'contextMenuHidden()',
|
|
284
|
+
'[textAlign]': 'textAlign()',
|
|
285
|
+
'[allowFontScaling]': 'allowFontScaling()',
|
|
286
|
+
'[maxFontSizeMultiplier]': 'maxFontSizeMultiplier()',
|
|
287
|
+
'[inputAccessoryViewID]': 'inputAccessoryViewID()',
|
|
288
|
+
'[clearButtonMode]': 'clearButtonMode()',
|
|
289
|
+
'[clearTextOnFocus]': 'clearTextOnFocus()',
|
|
290
|
+
'[enablesReturnKeyAutomatically]': 'enablesReturnKeyAutomatically()',
|
|
291
|
+
'[keyboardAppearance]': 'keyboardAppearance()',
|
|
292
|
+
'[passwordRules]': 'passwordRules()',
|
|
293
|
+
'[spellCheck]': 'spellCheck()',
|
|
294
|
+
'[smartInsertDelete]': 'smartInsertDelete()',
|
|
295
|
+
'[dataDetectorTypes]': 'dataDetectorTypes()',
|
|
296
|
+
'[textContentType]': 'textContentType()',
|
|
297
|
+
'[autoComplete]': 'autoComplete()',
|
|
298
|
+
'[underlineColorAndroid]': 'underlineColorAndroid()',
|
|
299
|
+
'[cursorColor]': 'cursorColor()',
|
|
300
|
+
'[selectionHandleColor]': 'selectionHandleColor()',
|
|
301
|
+
'[textAlignVertical]': 'textAlignVertical()',
|
|
302
|
+
'[importantForAutofill]': 'importantForAutofill()',
|
|
303
|
+
'[showSoftInputOnFocus]': 'showSoftInputOnFocus()',
|
|
304
|
+
'[disableFullscreenUI]': 'disableFullscreenUI()',
|
|
305
|
+
'[inlineImageLeft]': 'inlineImageLeft()',
|
|
306
|
+
'[inlineImagePadding]': 'inlineImagePadding()',
|
|
307
|
+
'[textBreakStrategy]': 'textBreakStrategy()',
|
|
308
|
+
'(change)': 'onNativeChange($event)',
|
|
309
|
+
},
|
|
310
|
+
}]
|
|
311
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changeText: [{ type: i0.Output, args: ["changeText"] }], touch: [{ type: i0.Output, args: ["touch"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], scrollEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollEnabled", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], placeholderTextColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderTextColor", required: false }] }], keyboardType: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardType", required: false }] }], returnKeyType: [{ type: i0.Input, args: [{ isSignal: true, alias: "returnKeyType", required: false }] }], submitBehavior: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitBehavior", required: false }] }], secureTextEntry: [{ type: i0.Input, args: [{ isSignal: true, alias: "secureTextEntry", required: false }] }], autoCapitalize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCapitalize", required: false }] }], autoCorrect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCorrect", required: false }] }], autoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFocus", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], numberOfLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "numberOfLines", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], selectionColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionColor", required: false }] }], selectTextOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectTextOnFocus", required: false }] }], caretHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "caretHidden", required: false }] }], contextMenuHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextMenuHidden", required: false }] }], textAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "textAlign", required: false }] }], allowFontScaling: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowFontScaling", required: false }] }], maxFontSizeMultiplier: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFontSizeMultiplier", required: false }] }], inputAccessoryViewID: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputAccessoryViewID", required: false }] }], clearButtonMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearButtonMode", required: false }] }], clearTextOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearTextOnFocus", required: false }] }], enablesReturnKeyAutomatically: [{ type: i0.Input, args: [{ isSignal: true, alias: "enablesReturnKeyAutomatically", required: false }] }], keyboardAppearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardAppearance", required: false }] }], passwordRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "passwordRules", required: false }] }], spellCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheck", required: false }] }], smartInsertDelete: [{ type: i0.Input, args: [{ isSignal: true, alias: "smartInsertDelete", required: false }] }], dataDetectorTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataDetectorTypes", required: false }] }], textContentType: [{ type: i0.Input, args: [{ isSignal: true, alias: "textContentType", required: false }] }], autoComplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoComplete", required: false }] }], underlineColorAndroid: [{ type: i0.Input, args: [{ isSignal: true, alias: "underlineColorAndroid", required: false }] }], cursorColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "cursorColor", required: false }] }], selectionHandleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionHandleColor", required: false }] }], textAlignVertical: [{ type: i0.Input, args: [{ isSignal: true, alias: "textAlignVertical", required: false }] }], importantForAutofill: [{ type: i0.Input, args: [{ isSignal: true, alias: "importantForAutofill", required: false }] }], showSoftInputOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSoftInputOnFocus", required: false }] }], disableFullscreenUI: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableFullscreenUI", required: false }] }], inlineImageLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineImageLeft", required: false }] }], inlineImagePadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineImagePadding", required: false }] }], textBreakStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "textBreakStrategy", required: false }] }] } });
|
|
312
|
+
//# sourceMappingURL=text-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-input.js","sourceRoot":"","sources":["../src/text-input.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Directive,\n type SimpleChanges,\n afterRenderEffect,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { Keyboard } from '@ng-native/device';\nimport type { NativeSyntheticEvent } from '@ng-native/fabric';\nimport { ControlledModel } from './controlled-model.ts';\nimport type { TextInputChangePayload } from './events.ts';\nimport { optionalBoolean, optionalNumber } from './transforms.ts';\nimport { ViewBase } from './view-base.ts';\n\nexport type KeyboardType =\n | 'default'\n | 'number-pad'\n | 'decimal-pad'\n | 'numeric'\n | 'email-address'\n | 'phone-pad'\n | 'url'\n | 'ascii-capable'\n | 'numbers-and-punctuation'\n | 'name-phone-pad'\n | 'twitter'\n | 'web-search'\n | 'visible-password';\nexport type ReturnKeyType =\n | 'done'\n | 'go'\n | 'next'\n | 'search'\n | 'send'\n | 'none'\n | 'previous'\n | 'default'\n | 'emergency-call'\n | 'google'\n | 'join'\n | 'route'\n | 'yahoo';\nexport type SubmitBehavior = 'submit' | 'blurAndSubmit' | 'newline';\n\n/**\n * A text field, wired for signal forms. Commits as `TextInput`, single or multi line by prop.\n *\n * `value` is a `model()`, which is all `FormValueControl<string>` requires, so binding it into a\n * form is `<text-input [formField]=\"f.name\" />` with no adapter class. The rest of the contract is\n * declared too, because Signal Forms only writes to inputs of those names: `disabled` and\n * `readonly` turn `editable` off, `invalid` and `touched` come out as `data-invalid` and\n * `data-touched` for a stylesheet, and `touch` fires from the native blur - there is no DOM one\n * for the form to hear instead. `(changeText)` carries\n * the new string alone, as RN's `onChangeText` does; the raw `(change)`, `(focus)`, `(blur)`,\n * `(submitEditing)`, `(endEditing)`, `(selectionChange)`, `(keyPress)`, `(contentSizeChange)`\n * and `(scroll)` are element events typed in `events.ts`.\n *\n * The interesting part is the echo. A native text field owns state the user is actively\n * changing, so JS and native disagree constantly. RN's protocol: native reports an `eventCount`\n * with every change, JS passes the most recent one back as a prop, and native ignores a `text`\n * update whose count is stale, meaning the user has typed since. Without it, a controlled input\n * fights the cursor and drops characters under fast typing.\n *\n * The other direction is native holding text the app does not: a value set from code after the\n * user has typed, or a keystroke the app refused or rewrote. It is controlled as RN's field is -\n * bind `value` and the app's value is what the field shows - so once each pass has rendered, the\n * field compares the model with the text native last reported and sends the difference as the\n * `setTextAndSelection` command. See `ControlledModel` for how a refusal reaches the model.\n * A value set that way is also measured again, since Fabric sizes the field from native state\n * that takes the new text only after measuring it: a composer cleared after sending shrinks.\n */\n@Directive({\n selector: 'text-input',\n exportAs: 'textInput',\n host: {\n '[text]': 'value()',\n '[mostRecentEventCount]': 'eventCount()',\n '[multiline]': 'multiline()',\n '[scrollEnabled]': 'scrollEnabled()',\n '[editable]': 'resolvedEditable()',\n // `disabled` is an input of ours, so it cannot reach `ngOnChanges` on the base; this is\n // the one binding that keeps the announced state in step with it.\n '[accessibilityState]': 'accessibilityStateProp()',\n '[attr.data-disabled]': \"disabled() ? '' : null\",\n '[attr.data-invalid]': \"invalid() ? '' : null\",\n '[attr.data-touched]': \"touched() ? '' : null\",\n '(blur)': 'touch.emit()',\n '(focus)': 'onFocus()',\n '[placeholder]': 'placeholder()',\n '[placeholderTextColor]': 'placeholderTextColor()',\n '[keyboardType]': 'keyboardType()',\n '[returnKeyType]': 'returnKeyType()',\n '[submitBehavior]': 'resolvedSubmitBehavior()',\n '[secureTextEntry]': 'secureTextEntry()',\n '[autoCapitalize]': 'autoCapitalize()',\n '[autoCorrect]': 'autoCorrect()',\n '[autoFocus]': 'autoFocus()',\n '[maxLength]': 'maxLength()',\n '[numberOfLines]': 'numberOfLines()',\n '[selection]': 'selection()',\n '[selectionColor]': 'selectionColor()',\n '[selectTextOnFocus]': 'selectTextOnFocus()',\n '[caretHidden]': 'caretHidden()',\n '[contextMenuHidden]': 'contextMenuHidden()',\n '[textAlign]': 'textAlign()',\n '[allowFontScaling]': 'allowFontScaling()',\n '[maxFontSizeMultiplier]': 'maxFontSizeMultiplier()',\n '[inputAccessoryViewID]': 'inputAccessoryViewID()',\n '[clearButtonMode]': 'clearButtonMode()',\n '[clearTextOnFocus]': 'clearTextOnFocus()',\n '[enablesReturnKeyAutomatically]': 'enablesReturnKeyAutomatically()',\n '[keyboardAppearance]': 'keyboardAppearance()',\n '[passwordRules]': 'passwordRules()',\n '[spellCheck]': 'spellCheck()',\n '[smartInsertDelete]': 'smartInsertDelete()',\n '[dataDetectorTypes]': 'dataDetectorTypes()',\n '[textContentType]': 'textContentType()',\n '[autoComplete]': 'autoComplete()',\n '[underlineColorAndroid]': 'underlineColorAndroid()',\n '[cursorColor]': 'cursorColor()',\n '[selectionHandleColor]': 'selectionHandleColor()',\n '[textAlignVertical]': 'textAlignVertical()',\n '[importantForAutofill]': 'importantForAutofill()',\n '[showSoftInputOnFocus]': 'showSoftInputOnFocus()',\n '[disableFullscreenUI]': 'disableFullscreenUI()',\n '[inlineImageLeft]': 'inlineImageLeft()',\n '[inlineImagePadding]': 'inlineImagePadding()',\n '[textBreakStrategy]': 'textBreakStrategy()',\n '(change)': 'onNativeChange($event)',\n },\n})\nexport class TextInput extends ViewBase {\n readonly value = model<string>('');\n /** The new text alone, on every native change. */\n readonly changeText = output<string>();\n /** Focus left the field. What Signal Forms marks a field touched from. */\n readonly touch = output<void>();\n\n /** Refuse input and announce as disabled. Wins over `editable`. */\n readonly disabled = input(undefined, { transform: optionalBoolean });\n /** Refuse input, though still announced as enabled. Wins over `editable`. */\n readonly readonly = input(undefined, { transform: optionalBoolean });\n /** Published as `data-invalid`; nothing native reads it. */\n readonly invalid = input(false, { transform: booleanAttribute });\n /** Published as `data-touched`; nothing native reads it. */\n readonly touched = input(false, { transform: booleanAttribute });\n\n /** Allow more than one line. */\n readonly multiline = input(undefined, { transform: optionalBoolean });\n /** iOS: whether a multiline field scrolls its text; off, it grows with it instead. */\n readonly scrollEnabled = input(undefined, { transform: optionalBoolean });\n /** Set to false to make the field read-only. */\n readonly editable = input(undefined, { transform: optionalBoolean });\n /** Shown while the field is empty. */\n readonly placeholder = input<string>();\n readonly placeholderTextColor = input<string>();\n /** Which keyboard to show. */\n readonly keyboardType = input<KeyboardType>();\n /** The label on the return key. */\n readonly returnKeyType = input<ReturnKeyType>();\n /** What return does. Defaults to `blurAndSubmit` on one line and `newline` on many. */\n readonly submitBehavior = input<SubmitBehavior>();\n /** Hide what is typed, for passwords. */\n readonly secureTextEntry = input(undefined, { transform: optionalBoolean });\n /** When the keyboard capitalises. Defaults to `sentences`. */\n readonly autoCapitalize = input<'none' | 'sentences' | 'words' | 'characters'>();\n /** Auto-correct while typing. Defaults to true. */\n readonly autoCorrect = input(undefined, { transform: optionalBoolean });\n /** Focus the field as soon as it mounts. */\n readonly autoFocus = input(undefined, { transform: optionalBoolean });\n /** The most characters allowed, enforced natively so nothing flickers. */\n readonly maxLength = input(undefined, { transform: optionalNumber });\n /** Android: the height of a multiline field, in lines. */\n readonly numberOfLines = input(undefined, { transform: optionalNumber });\n /** The selected range, or the caret when `start` equals `end`. */\n readonly selection = input<{ readonly start: number; readonly end?: number }>();\n readonly selectionColor = input<string>();\n /** Select everything on focus. */\n readonly selectTextOnFocus = input(undefined, { transform: optionalBoolean });\n readonly caretHidden = input(undefined, { transform: optionalBoolean });\n /** Disable the copy, paste and share menu. */\n readonly contextMenuHidden = input(undefined, { transform: optionalBoolean });\n readonly textAlign = input<'left' | 'center' | 'right'>();\n readonly allowFontScaling = input(undefined, { transform: optionalBoolean });\n readonly maxFontSizeMultiplier = input(undefined, { transform: optionalNumber });\n /** iOS: the `nativeID` of an `<input-accessory-view>` to dock above the keyboard. */\n readonly inputAccessoryViewID = input<string>();\n /** iOS: when the clear button shows. */\n readonly clearButtonMode = input<'never' | 'while-editing' | 'unless-editing' | 'always'>();\n /** iOS: empty the field on focus. */\n readonly clearTextOnFocus = input(undefined, { transform: optionalBoolean });\n /** iOS: disable the return key while the field is empty. */\n readonly enablesReturnKeyAutomatically = input(undefined, { transform: optionalBoolean });\n /** iOS: the keyboard's colour scheme. */\n readonly keyboardAppearance = input<'default' | 'light' | 'dark'>();\n /** iOS: rules for a generated password, in Apple's Password Rules syntax. */\n readonly passwordRules = input<string>();\n /** iOS: underline misspellings. Follows `autoCorrect` by default. */\n readonly spellCheck = input(undefined, { transform: optionalBoolean });\n /** iOS: add and remove spaces around pasted and deleted words. */\n readonly smartInsertDelete = input(undefined, { transform: optionalBoolean });\n /** iOS, multiline: turn phone numbers, links and addresses into taps. */\n readonly dataDetectorTypes = input<string | readonly string[]>();\n /** iOS: what the field holds, so the system can autofill it. */\n readonly textContentType = input<string>();\n /** Android: the autofill hint. */\n readonly autoComplete = input<string>();\n /**\n * Android: the underline colour, transparent by default.\n *\n * Not a taste call. Android's `EditText` carries the platform's own underline in its background\n * drawable, so a field with a border of its own draws two: the app's box, and a grey line\n * through it that turns blue on focus. React Native's `TextInput` defaults this prop to\n * `'transparent'` for exactly that reason, and this is that default rather than a new opinion.\n * Ignored on iOS, where the native field has no such chrome.\n */\n readonly underlineColorAndroid = input<string>('transparent');\n /** Android: the caret colour. */\n readonly cursorColor = input<string>();\n /** Android: the selection handle colour. */\n readonly selectionHandleColor = input<string>();\n /** Android: where text sits in a tall field. */\n readonly textAlignVertical = input<'auto' | 'top' | 'bottom' | 'center'>();\n /** Android: whether autofill may fill this field. */\n readonly importantForAutofill = input<\n 'auto' | 'no' | 'noExcludeDescendants' | 'yes' | 'yesExcludeDescendants'\n >();\n /** Android: set to false to focus without raising the keyboard. */\n readonly showSoftInputOnFocus = input(undefined, { transform: optionalBoolean });\n /** Android: keep the field in place in landscape rather than going full screen. */\n readonly disableFullscreenUI = input(undefined, { transform: optionalBoolean });\n /** Android: a drawable resource shown at the left of the field. */\n readonly inlineImageLeft = input<string>();\n readonly inlineImagePadding = input(undefined, { transform: optionalNumber });\n /** Android: the line-breaking strategy. */\n readonly textBreakStrategy = input<'simple' | 'highQuality' | 'balanced'>();\n\n protected readonly eventCount = signal(0);\n\n protected readonly resolvedEditable = computed(() =>\n this.disabled() || this.readonly() ? false : this.editable(),\n );\n\n protected override disabledForAccessibility(): boolean | undefined {\n return this.disabled();\n }\n\n protected readonly resolvedSubmitBehavior = computed(() => {\n const explicit = this.submitBehavior();\n // A single-line field has no line to add, so `newline` collapses to the default.\n if (explicit && (this.multiline() || explicit !== 'newline')) return explicit;\n return this.multiline() ? 'newline' : 'blurAndSubmit';\n });\n\n private readonly keyboard = inject(Keyboard);\n /** What native last reported, so a value set from code can be told from an echo. */\n private lastNativeText: string | null = null;\n private readonly control = new ControlledModel(this.value, 'value');\n\n constructor() {\n super();\n // RN's layout effect, keyed as RN keys it: the value, and the count every native change\n // moves on, so a refusal that leaves the value where it was is compared all the same. After\n // render rather than as an ordinary effect, because an accepted edit only reaches the model\n // during change detection, and comparing before it has would send the old text back.\n afterRenderEffect({\n write: () => {\n const desired = this.value();\n const count = this.eventCount();\n if (this.lastNativeText === null || this.lastNativeText === desired) return;\n // The `text` prop alone may be ignored as stale, so send it as a command with the count\n // native expects.\n this.lastNativeText = desired;\n this.engine.dispatchCommand(this.node, 'setTextAndSelection', [count, desired, -1, -1]);\n // Fabric sized the field for the text it had; see `HostEngine.remeasure`.\n this.engine.remeasure(this.node);\n },\n });\n }\n\n override ngOnChanges(changes: SimpleChanges): void {\n super.ngOnChanges(changes);\n this.control.noteChanges(changes);\n }\n\n /**\n * With the keyboard already up, keep the field clear of it. UIKit scrolls a field clear as the\n * keyboard rises, not when focus moves from one field to another beneath it, which is what a\n * form's Next key does; native form screens keep the new field on screen either way.\n */\n protected onFocus(): void {\n const { height, screenY } = this.keyboard.metrics();\n if (height > 0 && screenY !== undefined)\n this.engine.reveal(this.node, { visibleBottom: screenY });\n }\n\n /** Bring the keyboard up on this field. A view command, so it reaches native directly. */\n focus(): void {\n this.engine.dispatchCommand(this.node, 'focus');\n }\n\n blur(): void {\n this.engine.dispatchCommand(this.node, 'blur');\n }\n\n /** Empty the field. */\n clear(): void {\n this.value.set('');\n }\n\n /** Move the caret, or select a range. */\n setSelection(start: number, end = start): void {\n this.engine.dispatchCommand(this.node, 'setTextAndSelection', [\n this.eventCount(),\n null,\n start,\n end,\n ]);\n }\n\n /** Whether this field currently has the keyboard. */\n isFocused(): boolean {\n return this.engine.focused === this.node;\n }\n\n protected onNativeChange(event: NativeSyntheticEvent<Partial<TextInputChangePayload>>): void {\n const native = event.nativeEvent;\n const text = native?.text ?? '';\n // Order matters, as it does in RN: the value first, the count last.\n this.lastNativeText = text;\n this.control.propose(text);\n this.eventCount.set(native?.eventCount ?? this.eventCount() + 1);\n this.changeText.emit(text);\n }\n}\n"]}
|