@applicaster/zapp-react-native-ui-components 16.0.0-rc.34 → 16.0.0-rc.36
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/MasterCell/DefaultComponents/PressableView.tsx +27 -7
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +4 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +154 -138
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +0 -1
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +32 -21
- package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
- package/Components/MasterCell/hooks/index.ts +2 -0
- package/Components/MasterCell/hooks/usePressedState.ts +4 -0
- package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -69
- package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +25 -47
- package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +122 -39
- package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +257 -88
- package/Components/ModalComponent/AudioPlayer/Components/index.ts +6 -4
- package/package.json +5 -5
|
@@ -11,7 +11,14 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import React from "react";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
Image,
|
|
16
|
+
Platform,
|
|
17
|
+
Pressable,
|
|
18
|
+
StyleSheet,
|
|
19
|
+
Text,
|
|
20
|
+
View,
|
|
21
|
+
} from "react-native";
|
|
15
22
|
|
|
16
23
|
const styles = StyleSheet.create({
|
|
17
24
|
row: {
|
|
@@ -123,10 +130,11 @@ export type ActionData = {
|
|
|
123
130
|
showTrailingChevron?: boolean;
|
|
124
131
|
};
|
|
125
132
|
|
|
126
|
-
export type
|
|
133
|
+
export type AudioPlayerActionProps = {
|
|
127
134
|
configuration: ActionConfiguration;
|
|
128
135
|
data: ActionData;
|
|
129
136
|
focused?: boolean;
|
|
137
|
+
onPress?: () => void;
|
|
130
138
|
};
|
|
131
139
|
|
|
132
140
|
// ---------------------------------------------------------------------------
|
|
@@ -187,28 +195,32 @@ type ActionContainerProps = {
|
|
|
187
195
|
configuration: BackgroundConfiguration;
|
|
188
196
|
focused: boolean;
|
|
189
197
|
children: React.ReactNode;
|
|
198
|
+
onPress?: () => void;
|
|
190
199
|
};
|
|
191
200
|
|
|
192
201
|
function ActionContainer({
|
|
193
202
|
configuration,
|
|
194
203
|
focused,
|
|
195
204
|
children,
|
|
205
|
+
onPress,
|
|
196
206
|
}: ActionContainerProps) {
|
|
197
207
|
return (
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
208
|
+
<Pressable
|
|
209
|
+
onPress={onPress}
|
|
210
|
+
style={({ pressed }) => ({
|
|
211
|
+
backgroundColor:
|
|
212
|
+
pressed || focused
|
|
213
|
+
? configuration.focusedColor
|
|
214
|
+
: configuration.defaultColor,
|
|
203
215
|
borderRadius: configuration.cornerRadius,
|
|
204
216
|
paddingTop: CONTAINER_SPEC.paddingTop,
|
|
205
217
|
paddingRight: CONTAINER_SPEC.paddingRight,
|
|
206
218
|
paddingBottom: CONTAINER_SPEC.paddingBottom,
|
|
207
219
|
paddingLeft: CONTAINER_SPEC.paddingLeft,
|
|
208
|
-
}}
|
|
220
|
+
})}
|
|
209
221
|
>
|
|
210
222
|
{children}
|
|
211
|
-
</
|
|
223
|
+
</Pressable>
|
|
212
224
|
);
|
|
213
225
|
}
|
|
214
226
|
|
|
@@ -279,10 +291,15 @@ function ActionTrailingIcon({ configuration }: ActionTrailingIconProps) {
|
|
|
279
291
|
}
|
|
280
292
|
|
|
281
293
|
// ---------------------------------------------------------------------------
|
|
282
|
-
//
|
|
294
|
+
// AudioPlayerAction
|
|
283
295
|
// ---------------------------------------------------------------------------
|
|
284
296
|
|
|
285
|
-
export function
|
|
297
|
+
export function AudioPlayerAction({
|
|
298
|
+
configuration,
|
|
299
|
+
data,
|
|
300
|
+
focused = false,
|
|
301
|
+
onPress,
|
|
302
|
+
}: AudioPlayerActionProps) {
|
|
286
303
|
const { background, title, trailingIcon } = configuration;
|
|
287
304
|
const { title: label, leadingActionType, showTrailingChevron } = data;
|
|
288
305
|
|
|
@@ -290,7 +307,11 @@ export function Item({ configuration, data, focused = false }: ItemProps) {
|
|
|
290
307
|
const showTrailing = shouldShowTrailingIcon(showTrailingChevron);
|
|
291
308
|
|
|
292
309
|
return (
|
|
293
|
-
<ActionContainer
|
|
310
|
+
<ActionContainer
|
|
311
|
+
configuration={background}
|
|
312
|
+
focused={focused}
|
|
313
|
+
onPress={onPress}
|
|
314
|
+
>
|
|
294
315
|
<View style={styles.row}>
|
|
295
316
|
{showLeading ? (
|
|
296
317
|
<>
|
|
@@ -309,60 +330,3 @@ export function Item({ configuration, data, focused = false }: ItemProps) {
|
|
|
309
330
|
</ActionContainer>
|
|
310
331
|
);
|
|
311
332
|
}
|
|
312
|
-
|
|
313
|
-
// ---------------------------------------------------------------------------
|
|
314
|
-
// Demo
|
|
315
|
-
// ---------------------------------------------------------------------------
|
|
316
|
-
|
|
317
|
-
export default function App() {
|
|
318
|
-
return (
|
|
319
|
-
<View style={styles.demoScreen}>
|
|
320
|
-
<Text style={styles.demoHeading}>Modal Action Building Block</Text>
|
|
321
|
-
|
|
322
|
-
<Text style={styles.demoLabel}>
|
|
323
|
-
Leading icon + text — Add To Queue (focused)
|
|
324
|
-
</Text>
|
|
325
|
-
<Item
|
|
326
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
327
|
-
data={{ title: "Add To Queue", leadingActionType: "addToQueue" }}
|
|
328
|
-
focused
|
|
329
|
-
/>
|
|
330
|
-
|
|
331
|
-
<Text style={styles.demoLabel}>
|
|
332
|
-
Leading icon + text + trailing chevron — Add To Playlist
|
|
333
|
-
</Text>
|
|
334
|
-
<Item
|
|
335
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
336
|
-
data={{
|
|
337
|
-
title: "Add To Playlist",
|
|
338
|
-
leadingActionType: "addToPlaylist",
|
|
339
|
-
showTrailingChevron: true,
|
|
340
|
-
}}
|
|
341
|
-
/>
|
|
342
|
-
|
|
343
|
-
<Text style={styles.demoLabel}>Text only — Go To Playlist</Text>
|
|
344
|
-
<Item
|
|
345
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
346
|
-
data={{ title: "Go To Playlist" }}
|
|
347
|
-
/>
|
|
348
|
-
|
|
349
|
-
<Text style={styles.demoLabel}>Leading icon + text — Favorite</Text>
|
|
350
|
-
<Item
|
|
351
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
352
|
-
data={{ title: "Favorite", leadingActionType: "favorite" }}
|
|
353
|
-
/>
|
|
354
|
-
|
|
355
|
-
<Text style={styles.demoLabel}>Leading icon + text — Share</Text>
|
|
356
|
-
<Item
|
|
357
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
358
|
-
data={{ title: "Share", leadingActionType: "share" }}
|
|
359
|
-
/>
|
|
360
|
-
|
|
361
|
-
<Text style={styles.demoLabel}>Text only — Go To Artist</Text>
|
|
362
|
-
<Item
|
|
363
|
-
configuration={DEFAULT_ACTION_CONFIGURATION}
|
|
364
|
-
data={{ title: "Go To Artist" }}
|
|
365
|
-
/>
|
|
366
|
-
</View>
|
|
367
|
-
);
|
|
368
|
-
}
|
|
@@ -9,7 +9,14 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import React from "react";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
Image,
|
|
14
|
+
Platform,
|
|
15
|
+
Pressable,
|
|
16
|
+
StyleSheet,
|
|
17
|
+
Text,
|
|
18
|
+
View,
|
|
19
|
+
} from "react-native";
|
|
13
20
|
|
|
14
21
|
const styles = StyleSheet.create({
|
|
15
22
|
container: {
|
|
@@ -148,11 +155,12 @@ export type ButtonData = {
|
|
|
148
155
|
disabled?: boolean;
|
|
149
156
|
};
|
|
150
157
|
|
|
151
|
-
export type
|
|
158
|
+
export type AudioPlayerButtonProps = {
|
|
152
159
|
configuration: ButtonConfiguration;
|
|
153
160
|
data: ButtonData;
|
|
154
161
|
disabled?: boolean;
|
|
155
162
|
focused?: boolean;
|
|
163
|
+
onPress?: () => void;
|
|
156
164
|
};
|
|
157
165
|
|
|
158
166
|
// ---------------------------------------------------------------------------
|
|
@@ -170,7 +178,7 @@ const ACTION_ICON_ASSETS: Record<ButtonActionType, string> = {
|
|
|
170
178
|
confirm:
|
|
171
179
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAJElEQVR42mNgGAWjYBSQCv4TwKMWDHELho/hNE/3o2AUDDcAAPv0QMAyy1CtAAAAAElFTkSuQmCC",
|
|
172
180
|
cancel:
|
|
173
|
-
"data:image/png;base64,
|
|
181
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAASElEQVR42mNgGAWjGvynkVoUTf+pqA6nxv8UqiHbEooNx2cQ1QzHZiDVDcdlCcOQsoCmQUTTSKZpMqV5RqNLUUHTwm4UDBMAALBLQ73LTvoyAAAAAElFTkSuQmCC",
|
|
174
182
|
};
|
|
175
183
|
|
|
176
184
|
function getTextTransformStyle(
|
|
@@ -192,6 +200,7 @@ type ButtonContainerProps = {
|
|
|
192
200
|
disabled: boolean;
|
|
193
201
|
configuration: BackgroundConfiguration;
|
|
194
202
|
children: React.ReactNode;
|
|
203
|
+
onPress?: () => void;
|
|
195
204
|
};
|
|
196
205
|
|
|
197
206
|
function ButtonContainer({
|
|
@@ -199,19 +208,22 @@ function ButtonContainer({
|
|
|
199
208
|
disabled,
|
|
200
209
|
configuration,
|
|
201
210
|
children,
|
|
211
|
+
onPress,
|
|
202
212
|
}: ButtonContainerProps) {
|
|
203
|
-
const
|
|
213
|
+
const defaultBgColor = disabled
|
|
204
214
|
? configuration.inactiveColor
|
|
205
215
|
: focused
|
|
206
216
|
? configuration.focusedColor
|
|
207
217
|
: configuration.defaultColor;
|
|
208
218
|
|
|
209
219
|
return (
|
|
210
|
-
<
|
|
211
|
-
|
|
220
|
+
<Pressable
|
|
221
|
+
onPress={disabled ? undefined : onPress}
|
|
222
|
+
style={({ pressed }) => [
|
|
212
223
|
styles.container,
|
|
213
224
|
{
|
|
214
|
-
backgroundColor
|
|
225
|
+
backgroundColor:
|
|
226
|
+
pressed && !disabled ? configuration.focusedColor : defaultBgColor,
|
|
215
227
|
borderRadius: configuration.cornerRadius,
|
|
216
228
|
paddingTop: configuration.paddingTop,
|
|
217
229
|
paddingRight: configuration.paddingRight,
|
|
@@ -221,7 +233,7 @@ function ButtonContainer({
|
|
|
221
233
|
]}
|
|
222
234
|
>
|
|
223
235
|
{children}
|
|
224
|
-
</
|
|
236
|
+
</Pressable>
|
|
225
237
|
);
|
|
226
238
|
}
|
|
227
239
|
|
|
@@ -295,15 +307,16 @@ function ButtonLeadingIcon({
|
|
|
295
307
|
}
|
|
296
308
|
|
|
297
309
|
// ---------------------------------------------------------------------------
|
|
298
|
-
//
|
|
310
|
+
// AudioPlayerButton — single building block driven by configuration + data
|
|
299
311
|
// ---------------------------------------------------------------------------
|
|
300
312
|
|
|
301
|
-
export function
|
|
313
|
+
export function AudioPlayerButton({
|
|
302
314
|
configuration,
|
|
303
315
|
data,
|
|
304
316
|
disabled,
|
|
305
317
|
focused = false,
|
|
306
|
-
|
|
318
|
+
onPress,
|
|
319
|
+
}: AudioPlayerButtonProps) {
|
|
307
320
|
const {
|
|
308
321
|
background: backgroundConfiguration,
|
|
309
322
|
title: titleConfiguration,
|
|
@@ -321,6 +334,7 @@ export function Item({
|
|
|
321
334
|
focused={focused}
|
|
322
335
|
disabled={isDisabled}
|
|
323
336
|
configuration={backgroundConfiguration}
|
|
337
|
+
onPress={onPress}
|
|
324
338
|
>
|
|
325
339
|
<View style={styles.contentRow}>
|
|
326
340
|
{showIcon ? (
|
|
@@ -386,39 +400,3 @@ export const VARIANT_LARGE_ICON: ButtonConfiguration = {
|
|
|
386
400
|
},
|
|
387
401
|
},
|
|
388
402
|
};
|
|
389
|
-
|
|
390
|
-
export default function App() {
|
|
391
|
-
return (
|
|
392
|
-
<View style={styles.demoScreen}>
|
|
393
|
-
<Text style={styles.demoHeading}>Modal Button Building Block</Text>
|
|
394
|
-
|
|
395
|
-
<Text style={styles.demoLabel}>Variant 1 — Text only (confirmation)</Text>
|
|
396
|
-
<Item configuration={VARIANT_TEXT_ONLY} data={{ title: "Confirm" }} />
|
|
397
|
-
|
|
398
|
-
<Text style={styles.demoLabel}>Variant 2 — Leading icon + text</Text>
|
|
399
|
-
<Item
|
|
400
|
-
configuration={VARIANT_WITH_ICON}
|
|
401
|
-
data={{ title: "Add To Playlist" }}
|
|
402
|
-
/>
|
|
403
|
-
|
|
404
|
-
<Text style={styles.demoLabel}>Inactive state</Text>
|
|
405
|
-
<Item
|
|
406
|
-
configuration={VARIANT_TEXT_ONLY}
|
|
407
|
-
data={{ title: "Unavailable" }}
|
|
408
|
-
disabled
|
|
409
|
-
/>
|
|
410
|
-
|
|
411
|
-
<Text style={styles.demoLabel}>Custom title config — uppercase</Text>
|
|
412
|
-
<Item
|
|
413
|
-
configuration={VARIANT_UPPERCASE_TITLE}
|
|
414
|
-
data={{ title: "Save Changes" }}
|
|
415
|
-
/>
|
|
416
|
-
|
|
417
|
-
<Text style={styles.demoLabel}>Custom icons config — 32×32</Text>
|
|
418
|
-
<Item
|
|
419
|
-
configuration={VARIANT_LARGE_ICON}
|
|
420
|
-
data={{ title: "Add To Queue" }}
|
|
421
|
-
/>
|
|
422
|
-
</View>
|
|
423
|
-
);
|
|
424
|
-
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import React, { useCallback, useState } from "react";
|
|
12
|
-
import {
|
|
12
|
+
import { Platform, Pressable, StyleSheet, Text, View } from "react-native";
|
|
13
13
|
|
|
14
14
|
const styles = StyleSheet.create({
|
|
15
15
|
row: {
|
|
@@ -123,6 +123,7 @@ export type ActionButtonsStyleConfiguration = {
|
|
|
123
123
|
};
|
|
124
124
|
|
|
125
125
|
export type HeaderConfiguration = {
|
|
126
|
+
paddingTop: undefined;
|
|
126
127
|
variant: HeaderVariant;
|
|
127
128
|
title: TitleConfiguration;
|
|
128
129
|
closeButton: CloseButtonConfiguration;
|
|
@@ -168,12 +169,17 @@ export type HeaderData = {
|
|
|
168
169
|
title: string;
|
|
169
170
|
};
|
|
170
171
|
|
|
171
|
-
export type
|
|
172
|
+
export type AudioPlayerHeaderProps = {
|
|
172
173
|
configuration: HeaderConfiguration;
|
|
173
174
|
data: HeaderData;
|
|
174
175
|
focusedCloseButton?: boolean;
|
|
175
176
|
focusedLeadingAction?: boolean;
|
|
176
177
|
focusedTrailingAction?: boolean;
|
|
178
|
+
onClose?: () => void;
|
|
179
|
+
onBack?: () => void;
|
|
180
|
+
onCancel?: () => void;
|
|
181
|
+
onDone?: () => void;
|
|
182
|
+
onClear?: () => void;
|
|
177
183
|
};
|
|
178
184
|
|
|
179
185
|
// ---------------------------------------------------------------------------
|
|
@@ -202,9 +208,9 @@ type ActionButtonsBehaviorSpec = {
|
|
|
202
208
|
const CONTAINER_SPEC: Record<HeaderVariant, ContainerSpec> = {
|
|
203
209
|
singleLine: {
|
|
204
210
|
horizontalGutter: 16,
|
|
205
|
-
paddingTop:
|
|
206
|
-
paddingRight:
|
|
207
|
-
paddingBottom:
|
|
211
|
+
paddingTop: 24,
|
|
212
|
+
paddingRight: 20,
|
|
213
|
+
paddingBottom: 12,
|
|
208
214
|
paddingLeft: 20,
|
|
209
215
|
},
|
|
210
216
|
headerWithActions: {
|
|
@@ -256,9 +262,6 @@ const ACTION_BUTTONS_BEHAVIOR: Record<
|
|
|
256
262
|
},
|
|
257
263
|
};
|
|
258
264
|
|
|
259
|
-
const DEFAULT_CLOSE_BUTTON_ASSET =
|
|
260
|
-
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAAl0lEQVR42u2YQQ7AIAgE/f+naQ899dDYyiLT7DyAnRijwBjGGLNEnKCy4qJCNlVYKZ2aETeUshLhTGlZbUVh5UGkB8hlM4PKZDMCy2VXgrfJfhHYLvtGpI3sjFA72SextrKz0m1bUYwsTvhX97f9C4F8g5G/HLKPQHZqyF4YOW0g5znkxCytjV6koFZVqGVg5Yc0jDFmiQNENiwNUMoCZAAAAABJRU5ErkJggg==";
|
|
261
|
-
|
|
262
265
|
const CLOSE_BUTTON_SPEC = {
|
|
263
266
|
width: 44,
|
|
264
267
|
height: 44,
|
|
@@ -298,16 +301,26 @@ function shouldShowActionSlot(slot: ActionSlotSpec, sectionEnabled: boolean) {
|
|
|
298
301
|
|
|
299
302
|
type HeaderContainerProps = {
|
|
300
303
|
variant: HeaderVariant;
|
|
304
|
+
configuration: HeaderConfiguration;
|
|
301
305
|
children: React.ReactNode;
|
|
302
306
|
};
|
|
303
307
|
|
|
304
|
-
function HeaderContainer({
|
|
308
|
+
function HeaderContainer({
|
|
309
|
+
variant,
|
|
310
|
+
configuration,
|
|
311
|
+
children,
|
|
312
|
+
}: HeaderContainerProps) {
|
|
305
313
|
const container = CONTAINER_SPEC[variant];
|
|
306
314
|
|
|
315
|
+
const paddingTop =
|
|
316
|
+
configuration.paddingTop !== undefined
|
|
317
|
+
? configuration.paddingTop
|
|
318
|
+
: container.paddingTop;
|
|
319
|
+
|
|
307
320
|
return (
|
|
308
321
|
<View
|
|
309
322
|
style={{
|
|
310
|
-
paddingTop:
|
|
323
|
+
paddingTop: paddingTop,
|
|
311
324
|
paddingRight: container.paddingRight,
|
|
312
325
|
paddingBottom: container.paddingBottom,
|
|
313
326
|
paddingLeft: container.paddingLeft,
|
|
@@ -356,21 +369,80 @@ function HeaderTitle({ title, configuration, centered }: HeaderTitleProps) {
|
|
|
356
369
|
type HeaderCloseButtonProps = {
|
|
357
370
|
configuration: CloseButtonConfiguration;
|
|
358
371
|
focused?: boolean;
|
|
372
|
+
onPress?: () => void;
|
|
359
373
|
};
|
|
360
374
|
|
|
361
375
|
function HeaderCloseButton({
|
|
362
376
|
configuration,
|
|
363
377
|
focused = false,
|
|
378
|
+
onPress,
|
|
364
379
|
}: HeaderCloseButtonProps) {
|
|
365
380
|
if (!configuration.enabled) {
|
|
366
381
|
return null;
|
|
367
382
|
}
|
|
368
383
|
|
|
369
|
-
const
|
|
384
|
+
const buttonSize = 32;
|
|
370
385
|
|
|
371
386
|
return (
|
|
372
|
-
<
|
|
373
|
-
|
|
387
|
+
<Pressable
|
|
388
|
+
onPress={onPress}
|
|
389
|
+
style={({ pressed }) => [
|
|
390
|
+
styles.closeButton,
|
|
391
|
+
{
|
|
392
|
+
width: buttonSize,
|
|
393
|
+
height: buttonSize,
|
|
394
|
+
borderRadius: buttonSize / 2,
|
|
395
|
+
borderWidth: 1.5,
|
|
396
|
+
borderColor: "rgba(255, 255, 255, 0.4)",
|
|
397
|
+
opacity: pressed || focused ? 0.7 : 1,
|
|
398
|
+
justifyContent: "center",
|
|
399
|
+
alignItems: "center",
|
|
400
|
+
},
|
|
401
|
+
]}
|
|
402
|
+
>
|
|
403
|
+
<View
|
|
404
|
+
style={{
|
|
405
|
+
width: 14,
|
|
406
|
+
height: 14,
|
|
407
|
+
justifyContent: "center",
|
|
408
|
+
alignItems: "center",
|
|
409
|
+
}}
|
|
410
|
+
>
|
|
411
|
+
<View
|
|
412
|
+
style={{
|
|
413
|
+
position: "absolute",
|
|
414
|
+
width: 14,
|
|
415
|
+
height: 1.5,
|
|
416
|
+
backgroundColor: "#FFFFFF",
|
|
417
|
+
transform: [{ rotate: "45deg" }],
|
|
418
|
+
borderRadius: 1,
|
|
419
|
+
}}
|
|
420
|
+
/>
|
|
421
|
+
<View
|
|
422
|
+
style={{
|
|
423
|
+
position: "absolute",
|
|
424
|
+
width: 14,
|
|
425
|
+
height: 1.5,
|
|
426
|
+
backgroundColor: "#FFFFFF",
|
|
427
|
+
transform: [{ rotate: "-45deg" }],
|
|
428
|
+
borderRadius: 1,
|
|
429
|
+
}}
|
|
430
|
+
/>
|
|
431
|
+
</View>
|
|
432
|
+
</Pressable>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
type HeaderBackButtonProps = {
|
|
437
|
+
focused?: boolean;
|
|
438
|
+
onPress?: () => void;
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
function HeaderBackButton({ focused = false, onPress }: HeaderBackButtonProps) {
|
|
442
|
+
return (
|
|
443
|
+
<Pressable
|
|
444
|
+
onPress={onPress}
|
|
445
|
+
style={({ pressed }) => [
|
|
374
446
|
styles.closeButton,
|
|
375
447
|
{
|
|
376
448
|
width: CLOSE_BUTTON_SPEC.width,
|
|
@@ -382,19 +454,14 @@ function HeaderCloseButton({
|
|
|
382
454
|
borderRadius: CLOSE_BUTTON_SPEC.width / 2,
|
|
383
455
|
borderWidth: 1,
|
|
384
456
|
borderColor: "#FFFFFF",
|
|
385
|
-
opacity: focused ? 0.7 : 1,
|
|
457
|
+
opacity: pressed || focused ? 0.7 : 1,
|
|
386
458
|
},
|
|
387
459
|
]}
|
|
388
460
|
>
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
height: CLOSE_BUTTON_SPEC.height * 0.55,
|
|
394
|
-
}}
|
|
395
|
-
resizeMode="contain"
|
|
396
|
-
/>
|
|
397
|
-
</View>
|
|
461
|
+
<Text style={{ color: "#FFFFFF", fontSize: 20, fontWeight: "bold" }}>
|
|
462
|
+
‹
|
|
463
|
+
</Text>
|
|
464
|
+
</Pressable>
|
|
398
465
|
);
|
|
399
466
|
}
|
|
400
467
|
|
|
@@ -402,25 +469,29 @@ type HeaderActionButtonProps = {
|
|
|
402
469
|
actionType: HeaderActionType;
|
|
403
470
|
configuration: ActionButtonsStyleConfiguration;
|
|
404
471
|
focused?: boolean;
|
|
472
|
+
onPress?: () => void;
|
|
405
473
|
};
|
|
406
474
|
|
|
407
475
|
function HeaderActionButton({
|
|
408
476
|
actionType,
|
|
409
477
|
configuration,
|
|
410
478
|
focused = false,
|
|
479
|
+
onPress,
|
|
411
480
|
}: HeaderActionButtonProps) {
|
|
412
481
|
return (
|
|
413
|
-
<
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
482
|
+
<Pressable
|
|
483
|
+
onPress={onPress}
|
|
484
|
+
style={({ pressed }) => ({
|
|
485
|
+
backgroundColor:
|
|
486
|
+
pressed || focused
|
|
487
|
+
? configuration.focusedBackgroundColor
|
|
488
|
+
: configuration.defaultBackgroundColor,
|
|
418
489
|
borderRadius: ACTION_BUTTON_LAYOUT_SPEC.cornerRadius,
|
|
419
490
|
paddingTop: ACTION_BUTTON_LAYOUT_SPEC.paddingTop,
|
|
420
491
|
paddingRight: ACTION_BUTTON_LAYOUT_SPEC.paddingRight,
|
|
421
492
|
paddingBottom: ACTION_BUTTON_LAYOUT_SPEC.paddingBottom,
|
|
422
493
|
paddingLeft: ACTION_BUTTON_LAYOUT_SPEC.paddingLeft,
|
|
423
|
-
}}
|
|
494
|
+
})}
|
|
424
495
|
>
|
|
425
496
|
<Text
|
|
426
497
|
style={{
|
|
@@ -444,7 +515,7 @@ function HeaderActionButton({
|
|
|
444
515
|
>
|
|
445
516
|
{ACTION_LABELS[actionType]}
|
|
446
517
|
</Text>
|
|
447
|
-
</
|
|
518
|
+
</Pressable>
|
|
448
519
|
);
|
|
449
520
|
}
|
|
450
521
|
|
|
@@ -536,16 +607,21 @@ function CenterAlignedHeaderLayout({
|
|
|
536
607
|
}
|
|
537
608
|
|
|
538
609
|
// ---------------------------------------------------------------------------
|
|
539
|
-
//
|
|
610
|
+
// AudioPlayerHeader
|
|
540
611
|
// ---------------------------------------------------------------------------
|
|
541
612
|
|
|
542
|
-
export function
|
|
613
|
+
export function AudioPlayerHeader({
|
|
543
614
|
configuration,
|
|
544
615
|
data,
|
|
545
616
|
focusedCloseButton = false,
|
|
546
617
|
focusedLeadingAction = false,
|
|
547
618
|
focusedTrailingAction = false,
|
|
548
|
-
|
|
619
|
+
onClose,
|
|
620
|
+
onBack,
|
|
621
|
+
onCancel,
|
|
622
|
+
onDone,
|
|
623
|
+
onClear,
|
|
624
|
+
}: AudioPlayerHeaderProps) {
|
|
549
625
|
const { variant, title, closeButton, actionButtons } = configuration;
|
|
550
626
|
const { title: titleText } = data;
|
|
551
627
|
|
|
@@ -568,7 +644,10 @@ export function Item({
|
|
|
568
644
|
actionType={behavior.leading.actionType}
|
|
569
645
|
configuration={actionButtons}
|
|
570
646
|
focused={focusedLeadingAction}
|
|
647
|
+
onPress={onCancel}
|
|
571
648
|
/>
|
|
649
|
+
) : onBack ? (
|
|
650
|
+
<HeaderBackButton focused={focusedCloseButton} onPress={onBack} />
|
|
572
651
|
) : null;
|
|
573
652
|
|
|
574
653
|
const trailingContent = showTrailingAction ? (
|
|
@@ -576,17 +655,19 @@ export function Item({
|
|
|
576
655
|
actionType={behavior.trailing.actionType}
|
|
577
656
|
configuration={actionButtons}
|
|
578
657
|
focused={focusedTrailingAction}
|
|
658
|
+
onPress={behavior.trailing.actionType === "done" ? onDone : onClear}
|
|
579
659
|
/>
|
|
580
660
|
) : closeButton.enabled && !isCenterAligned ? (
|
|
581
661
|
<HeaderCloseButton
|
|
582
662
|
configuration={closeButton}
|
|
583
663
|
focused={focusedCloseButton}
|
|
664
|
+
onPress={onClose}
|
|
584
665
|
/>
|
|
585
666
|
) : null;
|
|
586
667
|
|
|
587
668
|
if (isCenterAligned) {
|
|
588
669
|
return (
|
|
589
|
-
<HeaderContainer variant={variant}>
|
|
670
|
+
<HeaderContainer variant={variant} configuration={configuration}>
|
|
590
671
|
<CenterAlignedHeaderLayout
|
|
591
672
|
horizontalGutter={container.horizontalGutter}
|
|
592
673
|
title={title}
|
|
@@ -599,7 +680,7 @@ export function Item({
|
|
|
599
680
|
}
|
|
600
681
|
|
|
601
682
|
return (
|
|
602
|
-
<HeaderContainer variant={variant}>
|
|
683
|
+
<HeaderContainer variant={variant} configuration={configuration}>
|
|
603
684
|
<View style={styles.row}>
|
|
604
685
|
{leadingContent ? (
|
|
605
686
|
<>
|
|
@@ -647,6 +728,7 @@ export const VARIANT_HEADER_WITH_ACTIONS: HeaderConfiguration = {
|
|
|
647
728
|
},
|
|
648
729
|
closeButton: { enabled: false },
|
|
649
730
|
actionButtons: DEFAULT_ACTION_BUTTONS_STYLE_CONFIGURATION,
|
|
731
|
+
paddingTop: 16,
|
|
650
732
|
};
|
|
651
733
|
|
|
652
734
|
/** Variant 2 — single side action (layout rule demo) */
|
|
@@ -665,6 +747,7 @@ export const VARIANT_HEADER_WITH_CANCEL_ONLY: HeaderConfiguration = {
|
|
|
665
747
|
},
|
|
666
748
|
closeButton: { enabled: false },
|
|
667
749
|
actionButtons: DEFAULT_ACTION_BUTTONS_STYLE_CONFIGURATION,
|
|
750
|
+
paddingTop: 16,
|
|
668
751
|
};
|
|
669
752
|
|
|
670
753
|
/** Variant 3 — Section Header */
|
|
@@ -692,7 +775,7 @@ export default function App() {
|
|
|
692
775
|
|
|
693
776
|
<View style={styles.demoBlock}>
|
|
694
777
|
<Text style={styles.demoLabel}>Single Line Header</Text>
|
|
695
|
-
<
|
|
778
|
+
<AudioPlayerHeader
|
|
696
779
|
configuration={VARIANT_SINGLE_LINE_HEADER}
|
|
697
780
|
data={{ title: "Playback Speed" }}
|
|
698
781
|
/>
|
|
@@ -700,7 +783,7 @@ export default function App() {
|
|
|
700
783
|
|
|
701
784
|
<View style={styles.demoBlock}>
|
|
702
785
|
<Text style={styles.demoLabel}>Header With Actions</Text>
|
|
703
|
-
<
|
|
786
|
+
<AudioPlayerHeader
|
|
704
787
|
configuration={VARIANT_HEADER_WITH_ACTIONS}
|
|
705
788
|
data={{ title: "Playback Speed" }}
|
|
706
789
|
/>
|
|
@@ -710,7 +793,7 @@ export default function App() {
|
|
|
710
793
|
<Text style={styles.demoLabel}>
|
|
711
794
|
Header With Actions — single side action
|
|
712
795
|
</Text>
|
|
713
|
-
<
|
|
796
|
+
<AudioPlayerHeader
|
|
714
797
|
configuration={VARIANT_HEADER_WITH_CANCEL_ONLY}
|
|
715
798
|
data={{ title: "Playback Speed" }}
|
|
716
799
|
/>
|
|
@@ -718,7 +801,7 @@ export default function App() {
|
|
|
718
801
|
|
|
719
802
|
<View style={styles.demoBlock}>
|
|
720
803
|
<Text style={styles.demoLabel}>Section Header</Text>
|
|
721
|
-
<
|
|
804
|
+
<AudioPlayerHeader
|
|
722
805
|
configuration={VARIANT_SECTION_HEADER}
|
|
723
806
|
data={{ title: "Next in Queue" }}
|
|
724
807
|
/>
|