UNPKG

11.1 kBJavaScriptView Raw
1import { booleanConverter } from '../core/view-base';
2// Requires.
3import { FormattedString } from './formatted-string';
4import { View } from '../core/view';
5import { Property, CssProperty, InheritedCssProperty, makeValidator, makeParser } from '../core/properties';
6import { Style } from '../styling/style';
7import { Observable } from '../../data/observable';
8import { parseCSSShadow } from '../styling/css-shadow';
9import { parseCSSStroke } from '../styling/css-stroke';
10const CHILD_SPAN = 'Span';
11const CHILD_FORMATTED_TEXT = 'formattedText';
12const CHILD_FORMATTED_STRING = 'FormattedString';
13export class TextBaseCommon extends View {
14 /***
15 * In the NativeScript Core; by default the nativeTextViewProtected points to the same value as nativeViewProtected.
16 * At this point no internal NS components need this indirection functionality.
17 * This indirection is used to allow support usage by third party components so they don't have to duplicate functionality.
18 *
19 * A third party component can just override the `nativeTextViewProtected` getter and return a different internal view and that view would be
20 * what all TextView/TextInput class features would be applied to.
21 *
22 * A example is the Android MaterialDesign TextInput class, it has a wrapper view of a TextInputLayout
23 * https://developer.android.com/reference/com/google/android/material/textfield/TextInputLayout
24 * which wraps the actual TextInput. This wrapper layout (TextInputLayout) must be assigned to the nativeViewProtected as the entire
25 * NS Core uses nativeViewProtected for everything related to layout, so that it can be measured, added to the parent view as a child, ect.
26 *
27 * However, its internal view would be the actual TextView/TextInput and to allow that sub-view to have the normal TextView/TextInput
28 * class features, which we expose and to allow them to work on it, the internal TextView/TextInput is what the needs to have the class values applied to it.
29 *
30 * So all code that works on what is expected to be a TextView/TextInput should use `nativeTextViewProtected` so that any third party
31 * components that need to have two separate components can work properly without them having to duplicate all the TextBase (and decendants) functionality
32 * by just overriding the nativeTextViewProtected getter.
33 **/
34 get nativeTextViewProtected() {
35 return this.nativeViewProtected;
36 }
37 get fontFamily() {
38 return this.style.fontFamily;
39 }
40 set fontFamily(value) {
41 this.style.fontFamily = value;
42 }
43 get fontSize() {
44 return this.style.fontSize;
45 }
46 set fontSize(value) {
47 this.style.fontSize = value;
48 }
49 get fontStyle() {
50 return this.style.fontStyle;
51 }
52 set fontStyle(value) {
53 this.style.fontStyle = value;
54 }
55 get fontWeight() {
56 return this.style.fontWeight;
57 }
58 set fontWeight(value) {
59 this.style.fontWeight = value;
60 }
61 get letterSpacing() {
62 return this.style.letterSpacing;
63 }
64 set letterSpacing(value) {
65 this.style.letterSpacing = value;
66 }
67 get lineHeight() {
68 return this.style.lineHeight;
69 }
70 set lineHeight(value) {
71 this.style.lineHeight = value;
72 }
73 get maxLines() {
74 return this.style.maxLines;
75 }
76 set maxLines(value) {
77 this.style.maxLines = value;
78 }
79 get textAlignment() {
80 return this.style.textAlignment;
81 }
82 set textAlignment(value) {
83 this.style.textAlignment = value;
84 }
85 get textDecoration() {
86 return this.style.textDecoration;
87 }
88 set textDecoration(value) {
89 this.style.textDecoration = value;
90 }
91 get textTransform() {
92 return this.style.textTransform;
93 }
94 set textTransform(value) {
95 this.style.textTransform = value;
96 }
97 get textShadow() {
98 return this.style.textShadow;
99 }
100 set textShadow(value) {
101 this.style.textShadow = value;
102 }
103 get whiteSpace() {
104 return this.style.whiteSpace;
105 }
106 set whiteSpace(value) {
107 this.style.whiteSpace = value;
108 }
109 get textOverflow() {
110 return this.style.textOverflow;
111 }
112 set textOverflow(value) {
113 this.style.textOverflow = value;
114 }
115 get padding() {
116 return this.style.padding;
117 }
118 set padding(value) {
119 this.style.padding = value;
120 }
121 get paddingTop() {
122 return this.style.paddingTop;
123 }
124 set paddingTop(value) {
125 this.style.paddingTop = value;
126 }
127 get paddingRight() {
128 return this.style.paddingRight;
129 }
130 set paddingRight(value) {
131 this.style.paddingRight = value;
132 }
133 get paddingBottom() {
134 return this.style.paddingBottom;
135 }
136 set paddingBottom(value) {
137 this.style.paddingBottom = value;
138 }
139 get paddingLeft() {
140 return this.style.paddingLeft;
141 }
142 set paddingLeft(value) {
143 this.style.paddingLeft = value;
144 }
145 _onFormattedTextContentsChanged(data) {
146 if (this.nativeViewProtected) {
147 // Notifications from the FormattedString start arriving before the Android view is even created.
148 this[formattedTextProperty.setNative](data.value);
149 }
150 }
151 _addChildFromBuilder(name, value) {
152 if (name === CHILD_SPAN) {
153 if (!this.formattedText) {
154 const formattedText = new FormattedString();
155 formattedText.spans.push(value);
156 this.formattedText = formattedText;
157 }
158 else {
159 this.formattedText.spans.push(value);
160 }
161 }
162 else if (name === CHILD_FORMATTED_TEXT || name === CHILD_FORMATTED_STRING) {
163 this.formattedText = value;
164 }
165 }
166 _requestLayoutOnTextChanged() {
167 this.requestLayout();
168 }
169 eachChild(callback) {
170 const text = this.formattedText;
171 if (text) {
172 callback(text);
173 }
174 }
175 _setNativeText(reset = false) {
176 //
177 }
178}
179TextBaseCommon.iosTextAnimationFallback = true;
180TextBaseCommon.prototype._isSingleLine = false;
181export function isBold(fontWeight) {
182 return fontWeight === 'bold' || fontWeight === '700' || fontWeight === '800' || fontWeight === '900';
183}
184export const textProperty = new Property({
185 name: 'text',
186 defaultValue: '',
187 affectsLayout: __ANDROID__,
188});
189textProperty.register(TextBaseCommon);
190export const formattedTextProperty = new Property({
191 name: 'formattedText',
192 affectsLayout: true,
193 valueChanged: onFormattedTextPropertyChanged,
194});
195formattedTextProperty.register(TextBaseCommon);
196export const iosTextAnimationProperty = new Property({
197 name: 'iosTextAnimation',
198 defaultValue: 'inherit',
199 affectsLayout: false,
200 valueConverter(value) {
201 try {
202 return booleanConverter(value);
203 }
204 catch (e) {
205 return 'inherit';
206 }
207 },
208});
209iosTextAnimationProperty.register(TextBaseCommon);
210function onFormattedTextPropertyChanged(textBase, oldValue, newValue) {
211 if (oldValue) {
212 oldValue.off(Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);
213 textBase._removeView(oldValue);
214 }
215 if (newValue) {
216 const oldParent = newValue.parent;
217 // In case formattedString is attached to new TextBase
218 if (oldParent) {
219 oldParent._removeView(newValue);
220 }
221 textBase._addView(newValue);
222 newValue.on(Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);
223 }
224}
225export function getClosestPropertyValue(property, span) {
226 if (property.isSet(span.style)) {
227 return span.style[property.name];
228 }
229 else if (property.isSet(span.parent.style)) {
230 // parent is FormattedString
231 return span.parent.style[property.name];
232 }
233 else if (property.isSet(span.parent.parent.style)) {
234 // parent.parent is TextBase
235 return span.parent.parent.style[property.name];
236 }
237}
238const textAlignmentConverter = makeParser(makeValidator('initial', 'left', 'center', 'right', 'justify'));
239export const textAlignmentProperty = new InheritedCssProperty({
240 name: 'textAlignment',
241 cssName: 'text-align',
242 defaultValue: 'initial',
243 valueConverter: textAlignmentConverter,
244});
245textAlignmentProperty.register(Style);
246const textTransformConverter = makeParser(makeValidator('initial', 'none', 'capitalize', 'uppercase', 'lowercase'));
247export const textTransformProperty = new CssProperty({
248 name: 'textTransform',
249 cssName: 'text-transform',
250 defaultValue: 'initial',
251 valueConverter: textTransformConverter,
252});
253textTransformProperty.register(Style);
254export const textShadowProperty = new CssProperty({
255 name: 'textShadow',
256 cssName: 'text-shadow',
257 affectsLayout: __APPLE__,
258 valueConverter: (value) => {
259 return parseCSSShadow(value);
260 },
261});
262textShadowProperty.register(Style);
263export const textStrokeProperty = new CssProperty({
264 name: 'textStroke',
265 cssName: 'text-stroke',
266 affectsLayout: __APPLE__,
267 valueConverter: (value) => {
268 return parseCSSStroke(value);
269 },
270});
271textStrokeProperty.register(Style);
272const whiteSpaceConverter = makeParser(makeValidator('initial', 'normal', 'nowrap'));
273export const whiteSpaceProperty = new CssProperty({
274 name: 'whiteSpace',
275 cssName: 'white-space',
276 defaultValue: 'initial',
277 affectsLayout: __APPLE__,
278 valueConverter: whiteSpaceConverter,
279});
280whiteSpaceProperty.register(Style);
281const textOverflowConverter = makeParser(makeValidator('clip', 'ellipsis', 'initial', 'unset'));
282export const textOverflowProperty = new CssProperty({
283 name: 'textOverflow',
284 cssName: 'text-overflow',
285 defaultValue: 'initial',
286 affectsLayout: __APPLE__,
287 valueConverter: textOverflowConverter,
288});
289textOverflowProperty.register(Style);
290const textDecorationConverter = makeParser(makeValidator('none', 'underline', 'line-through', 'underline line-through'));
291export const textDecorationProperty = new CssProperty({
292 name: 'textDecoration',
293 cssName: 'text-decoration',
294 defaultValue: 'none',
295 valueConverter: textDecorationConverter,
296});
297textDecorationProperty.register(Style);
298export const letterSpacingProperty = new InheritedCssProperty({
299 name: 'letterSpacing',
300 cssName: 'letter-spacing',
301 defaultValue: 0,
302 affectsLayout: __APPLE__,
303 valueConverter: (v) => parseFloat(v),
304});
305letterSpacingProperty.register(Style);
306export const lineHeightProperty = new InheritedCssProperty({
307 name: 'lineHeight',
308 cssName: 'line-height',
309 affectsLayout: __APPLE__,
310 valueConverter: (v) => parseFloat(v),
311});
312lineHeightProperty.register(Style);
313export const maxLinesProperty = new CssProperty({
314 name: 'maxLines',
315 cssName: 'max-lines',
316 valueConverter: (v) => (v === 'none' ? 0 : parseInt(v, 10)),
317});
318maxLinesProperty.register(Style);
319export const resetSymbol = Symbol('textPropertyDefault');
320//# sourceMappingURL=text-base-common.js.map
\No newline at end of file