@applicaster/zapp-react-native-ui-components 16.0.0-rc.85 → 16.0.0-rc.87
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/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +15 -0
- package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +1 -23
- package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +1 -36
- package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +1 -26
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +30 -25
- package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +7 -2
- package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +48 -1
- package/Components/ModalComponent/AudioPlayer/Components/index.ts +0 -2
- package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +18 -0
- package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +54 -0
- package/Components/ModalComponent/BottomSheetModalContent.tsx +92 -51
- package/Components/ModalComponent/SortableList.tsx +38 -23
- package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +17 -0
- package/Components/ModalComponent/index.tsx +7 -9
- package/Components/River/ComponentsMap/ComponentsMap.tsx +85 -59
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +138 -75
- package/Components/River/__tests__/componentsMap.test.js +8 -3
- package/Components/Screen/navigationHandler.ts +8 -8
- package/Contexts/ModalNavigationContext/__tests__/index.test.tsx +15 -0
- package/Contexts/ModalNavigationContext/index.tsx +2 -2
- package/package.json +5 -5
- package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +0 -314
|
@@ -11,6 +11,20 @@ type HookComponentProps = HookPluginProps & {
|
|
|
11
11
|
function GeneralContentScreenHookComponent(props: HookComponentProps) {
|
|
12
12
|
const { hookPlugin, focused, parentFocus } = props;
|
|
13
13
|
|
|
14
|
+
const componentsMapExtraPropsMemo = React.useMemo(
|
|
15
|
+
() => ({
|
|
16
|
+
safeArea: {
|
|
17
|
+
edges: {
|
|
18
|
+
top: "additive",
|
|
19
|
+
bottom: "additive",
|
|
20
|
+
left: "off",
|
|
21
|
+
right: "off",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
[]
|
|
26
|
+
);
|
|
27
|
+
|
|
14
28
|
if (!hookPlugin?.screen_id) {
|
|
15
29
|
log_error(
|
|
16
30
|
"GeneralContentScreenHookAdapter: This component should only be used as a hook, but no hookPlugin was provided."
|
|
@@ -26,6 +40,7 @@ function GeneralContentScreenHookComponent(props: HookComponentProps) {
|
|
|
26
40
|
isScreenWrappedInContainer={false}
|
|
27
41
|
focused={focused}
|
|
28
42
|
parentFocus={parentFocus}
|
|
43
|
+
componentsMapExtraProps={componentsMapExtraPropsMemo}
|
|
29
44
|
/>
|
|
30
45
|
</HookContentFocusGroup>
|
|
31
46
|
);
|
|
@@ -363,7 +363,7 @@ export function AudioPlayerButton({
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
// ---------------------------------------------------------------------------
|
|
366
|
-
//
|
|
366
|
+
// Variant configurations
|
|
367
367
|
// ---------------------------------------------------------------------------
|
|
368
368
|
|
|
369
369
|
export const VARIANT_TEXT_ONLY: ButtonConfiguration = {
|
|
@@ -383,25 +383,3 @@ export const VARIANT_WITH_ICON: ButtonConfiguration = {
|
|
|
383
383
|
},
|
|
384
384
|
},
|
|
385
385
|
};
|
|
386
|
-
|
|
387
|
-
export const VARIANT_UPPERCASE_TITLE: ButtonConfiguration = {
|
|
388
|
-
background: DEFAULT_BACKGROUND_CONFIGURATION,
|
|
389
|
-
title: {
|
|
390
|
-
...DEFAULT_TITLE_CONFIGURATION,
|
|
391
|
-
textTransform: "uppercase",
|
|
392
|
-
},
|
|
393
|
-
icons: DEFAULT_ICONS_CONFIGURATION,
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
export const VARIANT_LARGE_ICON: ButtonConfiguration = {
|
|
397
|
-
background: DEFAULT_BACKGROUND_CONFIGURATION,
|
|
398
|
-
title: DEFAULT_TITLE_CONFIGURATION,
|
|
399
|
-
icons: {
|
|
400
|
-
width: 32,
|
|
401
|
-
height: 32,
|
|
402
|
-
leadingIcon: {
|
|
403
|
-
enabled: true,
|
|
404
|
-
actionType: "addToQueue",
|
|
405
|
-
},
|
|
406
|
-
},
|
|
407
|
-
};
|
|
@@ -63,11 +63,7 @@ export type TextTransform =
|
|
|
63
63
|
export type TitleAlignment = "left" | "center";
|
|
64
64
|
|
|
65
65
|
/** Selects hardcoded container + action layout (white fields). */
|
|
66
|
-
export type HeaderVariant =
|
|
67
|
-
| "singleLine"
|
|
68
|
-
| "headerWithActions"
|
|
69
|
-
| "headerWithActionsCancelOnly"
|
|
70
|
-
| "section";
|
|
66
|
+
export type HeaderVariant = "singleLine" | "headerWithActions" | "section";
|
|
71
67
|
|
|
72
68
|
export type TitleConfiguration = {
|
|
73
69
|
fontColor: string;
|
|
@@ -198,13 +194,6 @@ const CONTAINER_SPEC: Record<HeaderVariant, ContainerSpec> = {
|
|
|
198
194
|
paddingBottom: 8,
|
|
199
195
|
paddingLeft: 20,
|
|
200
196
|
},
|
|
201
|
-
headerWithActionsCancelOnly: {
|
|
202
|
-
horizontalGutter: 12,
|
|
203
|
-
paddingTop: 0,
|
|
204
|
-
paddingRight: 20,
|
|
205
|
-
paddingBottom: 8,
|
|
206
|
-
paddingLeft: 20,
|
|
207
|
-
},
|
|
208
197
|
section: {
|
|
209
198
|
horizontalGutter: 12,
|
|
210
199
|
paddingTop: 0,
|
|
@@ -228,11 +217,6 @@ const ACTION_BUTTONS_BEHAVIOR: Record<
|
|
|
228
217
|
leading: { enabled: true, actionType: "cancel" },
|
|
229
218
|
trailing: { enabled: true, actionType: "done" },
|
|
230
219
|
},
|
|
231
|
-
headerWithActionsCancelOnly: {
|
|
232
|
-
sectionEnabled: true,
|
|
233
|
-
leading: { enabled: true, actionType: "cancel" },
|
|
234
|
-
trailing: { enabled: false },
|
|
235
|
-
},
|
|
236
220
|
section: {
|
|
237
221
|
sectionEnabled: true,
|
|
238
222
|
leading: { enabled: false },
|
|
@@ -725,25 +709,6 @@ export const VARIANT_HEADER_WITH_ACTIONS: HeaderConfiguration = {
|
|
|
725
709
|
paddingTop: 16,
|
|
726
710
|
};
|
|
727
711
|
|
|
728
|
-
/** Variant 2 — single side action (layout rule demo) */
|
|
729
|
-
export const VARIANT_HEADER_WITH_CANCEL_ONLY: HeaderConfiguration = {
|
|
730
|
-
variant: "headerWithActionsCancelOnly",
|
|
731
|
-
title: {
|
|
732
|
-
fontColor: "#FFFFFF",
|
|
733
|
-
iosFontFamily: "SFProText-Bold",
|
|
734
|
-
androidFontFamily: "Roboto-Bold",
|
|
735
|
-
fontSize: 22,
|
|
736
|
-
lineHeight: 28,
|
|
737
|
-
iosLetterSpacing: -0.6,
|
|
738
|
-
androidLetterSpacing: 0,
|
|
739
|
-
textTransform: "default",
|
|
740
|
-
alignment: "center",
|
|
741
|
-
},
|
|
742
|
-
closeButton: { enabled: false },
|
|
743
|
-
actionButtons: DEFAULT_ACTION_BUTTONS_STYLE_CONFIGURATION,
|
|
744
|
-
paddingTop: 16,
|
|
745
|
-
};
|
|
746
|
-
|
|
747
712
|
/** Variant 3 — Section Header */
|
|
748
713
|
export const VARIANT_SECTION_HEADER: HeaderConfiguration = {
|
|
749
714
|
variant: "section",
|
|
@@ -565,7 +565,7 @@ export function AudioPlayerInput({
|
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
// ---------------------------------------------------------------------------
|
|
568
|
-
// Variant
|
|
568
|
+
// Variant configurations
|
|
569
569
|
// ---------------------------------------------------------------------------
|
|
570
570
|
|
|
571
571
|
/** Search pill — leading icon + clear button */
|
|
@@ -626,28 +626,3 @@ export const VARIANT_NAME_PLAYLIST_INPUT: InputConfiguration = {
|
|
|
626
626
|
},
|
|
627
627
|
},
|
|
628
628
|
};
|
|
629
|
-
|
|
630
|
-
/** Text only search pill — no leading icon */
|
|
631
|
-
export const VARIANT_TEXT_ONLY_INPUT: InputConfiguration = {
|
|
632
|
-
background: DEFAULT_BACKGROUND_CONFIGURATION,
|
|
633
|
-
label: DEFAULT_LABEL_CONFIGURATION,
|
|
634
|
-
text: DEFAULT_TEXT_CONFIGURATION,
|
|
635
|
-
icons: {
|
|
636
|
-
...DEFAULT_ICONS_CONFIGURATION,
|
|
637
|
-
leadingIcon: { enabled: false },
|
|
638
|
-
},
|
|
639
|
-
};
|
|
640
|
-
|
|
641
|
-
/** Search without clear button */
|
|
642
|
-
export const VARIANT_SEARCH_WITHOUT_CLEAR: InputConfiguration = {
|
|
643
|
-
background: DEFAULT_BACKGROUND_CONFIGURATION,
|
|
644
|
-
label: DEFAULT_LABEL_CONFIGURATION,
|
|
645
|
-
text: DEFAULT_TEXT_CONFIGURATION,
|
|
646
|
-
icons: {
|
|
647
|
-
...DEFAULT_ICONS_CONFIGURATION,
|
|
648
|
-
trailingIcon: {
|
|
649
|
-
...DEFAULT_ICONS_CONFIGURATION.trailingIcon,
|
|
650
|
-
enabled: false,
|
|
651
|
-
},
|
|
652
|
-
},
|
|
653
|
-
};
|
|
@@ -12,14 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import React from "react";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
Platform,
|
|
18
|
-
Pressable,
|
|
19
|
-
StyleSheet,
|
|
20
|
-
Text,
|
|
21
|
-
View,
|
|
22
|
-
} from "react-native";
|
|
15
|
+
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
|
|
16
|
+
import { Platform, Pressable, StyleSheet, Text, View } from "react-native";
|
|
23
17
|
import {
|
|
24
18
|
MenuItem,
|
|
25
19
|
SelectionBehavior,
|
|
@@ -291,13 +285,14 @@ function resolveContainerSpec(image: ImageConfiguration): ContainerSpec {
|
|
|
291
285
|
|
|
292
286
|
export function mapMenuItemToNowPlayingData(
|
|
293
287
|
item: MenuItem,
|
|
294
|
-
isPaused?: boolean
|
|
288
|
+
isPaused?: boolean,
|
|
289
|
+
nowPlayingLabel = "Now Playing"
|
|
295
290
|
): ItemData {
|
|
296
291
|
return {
|
|
297
292
|
imageUri: item.icon,
|
|
298
293
|
textLabel1: item.title,
|
|
299
294
|
textLabel2: item.summary ?? "",
|
|
300
|
-
nowPlayingLabel
|
|
295
|
+
nowPlayingLabel,
|
|
301
296
|
trailingButton: "playPause",
|
|
302
297
|
isSelected: isPaused !== undefined ? !isPaused : item.isSelected,
|
|
303
298
|
};
|
|
@@ -402,6 +397,10 @@ type ItemLabelProps = {
|
|
|
402
397
|
};
|
|
403
398
|
|
|
404
399
|
function ItemLabel({ text, configuration, focused = false }: ItemLabelProps) {
|
|
400
|
+
if (!text) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
|
|
405
404
|
const color =
|
|
406
405
|
focused && configuration.focusedFontColor
|
|
407
406
|
? configuration.focusedFontColor
|
|
@@ -878,22 +877,28 @@ export function AudioPlayerTrackItem({
|
|
|
878
877
|
<View style={{ width: container.horizontalGutter }} />
|
|
879
878
|
<View style={styles.contentColumn}>
|
|
880
879
|
{showNowPlaying ? (
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
880
|
+
<NowPlayingRow
|
|
881
|
+
assetConfiguration={nowPlayingAsset}
|
|
882
|
+
labelConfiguration={nowPlayingLabel}
|
|
883
|
+
label={data.nowPlayingLabel}
|
|
884
|
+
/>
|
|
885
|
+
) : null}
|
|
886
|
+
{showNowPlaying && (data.textLabel1 || data.textLabel2) ? (
|
|
887
|
+
<View style={{ height: container.verticalGutter }} />
|
|
888
|
+
) : null}
|
|
889
|
+
{data.textLabel1 ? (
|
|
890
|
+
<ItemLabel
|
|
891
|
+
text={data.textLabel1}
|
|
892
|
+
configuration={textLabel1}
|
|
893
|
+
focused={focused}
|
|
894
|
+
/>
|
|
895
|
+
) : null}
|
|
896
|
+
{data.textLabel1 && data.textLabel2 ? (
|
|
897
|
+
<View style={{ height: container.verticalGutter }} />
|
|
898
|
+
) : null}
|
|
899
|
+
{data.textLabel2 ? (
|
|
900
|
+
<ItemLabel text={data.textLabel2} configuration={textLabel2} />
|
|
889
901
|
) : null}
|
|
890
|
-
<ItemLabel
|
|
891
|
-
text={data.textLabel1}
|
|
892
|
-
configuration={textLabel1}
|
|
893
|
-
focused={focused}
|
|
894
|
-
/>
|
|
895
|
-
<View style={{ height: container.verticalGutter }} />
|
|
896
|
-
<ItemLabel text={data.textLabel2} configuration={textLabel2} />
|
|
897
902
|
</View>
|
|
898
903
|
<ItemButtons
|
|
899
904
|
leadingButton={data.leadingButton}
|
|
@@ -21,10 +21,14 @@ const styles = StyleSheet.create({
|
|
|
21
21
|
|
|
22
22
|
type NowPlayingHeaderSectionProps = {
|
|
23
23
|
onClear?: () => void;
|
|
24
|
+
nextUpTitle?: string;
|
|
25
|
+
nowPlayingTitle?: string;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
export function NowPlayingHeaderSection({
|
|
27
29
|
onClear,
|
|
30
|
+
nextUpTitle = "Next Up",
|
|
31
|
+
nowPlayingTitle = "Now Playing",
|
|
28
32
|
}: NowPlayingHeaderSectionProps) {
|
|
29
33
|
const player = usePlayer();
|
|
30
34
|
const playerState = usePlayerState("queue-now-playing-section");
|
|
@@ -53,7 +57,8 @@ export function NowPlayingHeaderSection({
|
|
|
53
57
|
|
|
54
58
|
const data = mapMenuItemToNowPlayingData(
|
|
55
59
|
nowPlayingItem,
|
|
56
|
-
playerState?.isPaused
|
|
60
|
+
playerState?.isPaused,
|
|
61
|
+
nowPlayingTitle
|
|
57
62
|
);
|
|
58
63
|
|
|
59
64
|
const handlePlayPause = () => {
|
|
@@ -81,7 +86,7 @@ export function NowPlayingHeaderSection({
|
|
|
81
86
|
{renderNowPlayingTrack()}
|
|
82
87
|
<AudioPlayerHeader
|
|
83
88
|
configuration={VARIANT_SECTION_HEADER}
|
|
84
|
-
data={{ title:
|
|
89
|
+
data={{ title: nextUpTitle }}
|
|
85
90
|
onClear={onClear}
|
|
86
91
|
/>
|
|
87
92
|
</View>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Pressable } from "react-native";
|
|
3
3
|
import { fireEvent, render, screen } from "@testing-library/react-native";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AudioPlayerTrackItem,
|
|
6
|
+
VARIANT_PLAYLIST_ITEM,
|
|
7
|
+
mapMenuItemToNowPlayingData,
|
|
8
|
+
} from "../Item";
|
|
5
9
|
|
|
6
10
|
const playlistItemData = {
|
|
7
11
|
textLabel1: "Queue",
|
|
@@ -63,4 +67,47 @@ describe("AudioPlayerTrackItem multiSelect checkbox", () => {
|
|
|
63
67
|
|
|
64
68
|
expect(onPress).toHaveBeenCalledTimes(1);
|
|
65
69
|
});
|
|
70
|
+
|
|
71
|
+
it("renders only textLabel1 Text element when textLabel2 is missing or empty", () => {
|
|
72
|
+
const { UNSAFE_getAllByType, queryByText } = render(
|
|
73
|
+
<AudioPlayerTrackItem
|
|
74
|
+
configuration={VARIANT_PLAYLIST_ITEM}
|
|
75
|
+
data={{
|
|
76
|
+
textLabel1: "Only Title",
|
|
77
|
+
textLabel2: "",
|
|
78
|
+
}}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const { Text } = require("react-native");
|
|
83
|
+
const textNodes = UNSAFE_getAllByType(Text);
|
|
84
|
+
expect(textNodes).toHaveLength(1);
|
|
85
|
+
expect(queryByText("Only Title")).toBeTruthy();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe("mapMenuItemToNowPlayingData", () => {
|
|
90
|
+
const item = {
|
|
91
|
+
id: "item_1",
|
|
92
|
+
title: "Track Title",
|
|
93
|
+
summary: "Artist Name",
|
|
94
|
+
icon: "https://example.com/cover.png",
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
it("uses default 'Now Playing' label when omitted", () => {
|
|
98
|
+
const data = mapMenuItemToNowPlayingData(item as any);
|
|
99
|
+
expect(data.nowPlayingLabel).toBe("Now Playing");
|
|
100
|
+
expect(data.textLabel1).toBe("Track Title");
|
|
101
|
+
expect(data.textLabel2).toBe("Artist Name");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("uses custom nowPlayingLabel when provided", () => {
|
|
105
|
+
const data = mapMenuItemToNowPlayingData(
|
|
106
|
+
item as any,
|
|
107
|
+
false,
|
|
108
|
+
"En cours de lecture"
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(data.nowPlayingLabel).toBe("En cours de lecture");
|
|
112
|
+
});
|
|
66
113
|
});
|
|
@@ -227,4 +227,22 @@ describe("mergeButtonConfiguration background", () => {
|
|
|
227
227
|
"https://placehold.co/24x24/FF00FF/FFFFFF/png?text=CN"
|
|
228
228
|
);
|
|
229
229
|
});
|
|
230
|
+
|
|
231
|
+
it("applies Studio button title typography (fontFamily, letterSpacing, textTransform)", () => {
|
|
232
|
+
const merged = mergeButtonConfiguration(buttonBase as any, {
|
|
233
|
+
title: {
|
|
234
|
+
default: {
|
|
235
|
+
fontFamily: "CustomFont",
|
|
236
|
+
letterSpacing: -0.5,
|
|
237
|
+
textTransform: "uppercase",
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
expect(merged.title.iosFontFamily).toBe("CustomFont");
|
|
243
|
+
expect(merged.title.androidFontFamily).toBe("CustomFont");
|
|
244
|
+
expect(merged.title.iosLetterSpacing).toBe(-0.5);
|
|
245
|
+
expect(merged.title.androidLetterSpacing).toBe(-0.5);
|
|
246
|
+
expect(merged.title.textTransform).toBe("uppercase");
|
|
247
|
+
});
|
|
230
248
|
});
|
|
@@ -93,6 +93,33 @@ function mergeItemLabel(
|
|
|
93
93
|
...(override.lineHeight !== undefined
|
|
94
94
|
? { lineHeight: override.lineHeight }
|
|
95
95
|
: {}),
|
|
96
|
+
...(override.fontFamily
|
|
97
|
+
? {
|
|
98
|
+
iosFontFamily: override.fontFamily,
|
|
99
|
+
androidFontFamily: override.fontFamily,
|
|
100
|
+
}
|
|
101
|
+
: {}),
|
|
102
|
+
...(override.iosFontFamily
|
|
103
|
+
? { iosFontFamily: override.iosFontFamily }
|
|
104
|
+
: {}),
|
|
105
|
+
...(override.androidFontFamily
|
|
106
|
+
? { androidFontFamily: override.androidFontFamily }
|
|
107
|
+
: {}),
|
|
108
|
+
...(override.letterSpacing !== undefined
|
|
109
|
+
? {
|
|
110
|
+
iosLetterSpacing: override.letterSpacing,
|
|
111
|
+
androidLetterSpacing: override.letterSpacing,
|
|
112
|
+
}
|
|
113
|
+
: {}),
|
|
114
|
+
...(override.iosLetterSpacing !== undefined
|
|
115
|
+
? { iosLetterSpacing: override.iosLetterSpacing }
|
|
116
|
+
: {}),
|
|
117
|
+
...(override.androidLetterSpacing !== undefined
|
|
118
|
+
? { androidLetterSpacing: override.androidLetterSpacing }
|
|
119
|
+
: {}),
|
|
120
|
+
...(override.textTransform
|
|
121
|
+
? { textTransform: override.textTransform }
|
|
122
|
+
: {}),
|
|
96
123
|
};
|
|
97
124
|
}
|
|
98
125
|
|
|
@@ -267,6 +294,33 @@ function mergeButtonTitle(
|
|
|
267
294
|
...(override.lineHeight !== undefined
|
|
268
295
|
? { lineHeight: override.lineHeight }
|
|
269
296
|
: {}),
|
|
297
|
+
...(override.fontFamily
|
|
298
|
+
? {
|
|
299
|
+
iosFontFamily: override.fontFamily,
|
|
300
|
+
androidFontFamily: override.fontFamily,
|
|
301
|
+
}
|
|
302
|
+
: {}),
|
|
303
|
+
...(override.iosFontFamily
|
|
304
|
+
? { iosFontFamily: override.iosFontFamily }
|
|
305
|
+
: {}),
|
|
306
|
+
...(override.androidFontFamily
|
|
307
|
+
? { androidFontFamily: override.androidFontFamily }
|
|
308
|
+
: {}),
|
|
309
|
+
...(override.letterSpacing !== undefined
|
|
310
|
+
? {
|
|
311
|
+
iosLetterSpacing: override.letterSpacing,
|
|
312
|
+
androidLetterSpacing: override.letterSpacing,
|
|
313
|
+
}
|
|
314
|
+
: {}),
|
|
315
|
+
...(override.iosLetterSpacing !== undefined
|
|
316
|
+
? { iosLetterSpacing: override.iosLetterSpacing }
|
|
317
|
+
: {}),
|
|
318
|
+
...(override.androidLetterSpacing !== undefined
|
|
319
|
+
? { androidLetterSpacing: override.androidLetterSpacing }
|
|
320
|
+
: {}),
|
|
321
|
+
...(override.textTransform
|
|
322
|
+
? { textTransform: override.textTransform }
|
|
323
|
+
: {}),
|
|
270
324
|
};
|
|
271
325
|
}
|
|
272
326
|
|