jfs-components 0.1.35 → 0.1.48
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/CHANGELOG.md +43 -0
- package/D2C.md +82 -87
- package/lib/commonjs/components/Accordion/Accordion.js +16 -3
- package/lib/commonjs/components/AppBar/AppBar.js +118 -93
- package/lib/commonjs/components/CompareTable/CompareTable.js +98 -33
- package/lib/commonjs/components/FormField/FormField.js +9 -1
- package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +4 -14
- package/lib/commonjs/components/HelloJioInput/HelloJioInput.js +20 -4
- package/lib/commonjs/components/PageHero/PageHero.js +3 -0
- package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +50 -30
- package/lib/commonjs/components/ValueBackMetric/ValueBackMetric.js +117 -89
- package/lib/commonjs/components/index.js +7 -1
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -42204
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/Accordion/Accordion.js +16 -3
- package/lib/module/components/AppBar/AppBar.js +116 -93
- package/lib/module/components/CompareTable/CompareTable.js +99 -34
- package/lib/module/components/FormField/FormField.js +9 -1
- package/lib/module/components/FullscreenModal/FullscreenModal.js +4 -14
- package/lib/module/components/HelloJioInput/HelloJioInput.js +20 -4
- package/lib/module/components/PageHero/PageHero.js +3 -0
- package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +50 -30
- package/lib/module/components/ValueBackMetric/ValueBackMetric.js +120 -93
- package/lib/module/components/index.js +1 -1
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -42204
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/Accordion/Accordion.d.ts +14 -1
- package/lib/typescript/src/components/AppBar/AppBar.d.ts +46 -14
- package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +29 -12
- package/lib/typescript/src/components/HelloJioInput/HelloJioInput.d.ts +6 -4
- package/lib/typescript/src/components/PageHero/PageHero.d.ts +1 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +8 -1
- package/lib/typescript/src/components/ValueBackMetric/ValueBackMetric.d.ts +27 -16
- package/lib/typescript/src/components/index.d.ts +1 -1
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +3 -1
- package/scripts/extract-figma-modes.js +150 -121
- package/src/components/Accordion/Accordion.tsx +61 -33
- package/src/components/AppBar/AppBar.tsx +154 -124
- package/src/components/CompareTable/CompareTable.tsx +138 -52
- package/src/components/FormField/FormField.tsx +7 -0
- package/src/components/FullscreenModal/FullscreenModal.tsx +5 -14
- package/src/components/HelloJioInput/HelloJioInput.tsx +31 -12
- package/src/components/PageHero/PageHero.tsx +5 -0
- package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +63 -30
- package/src/components/ValueBackMetric/ValueBackMetric.tsx +178 -104
- package/src/components/index.ts +6 -1
- package/src/design-tokens/Coin Variables-variables-full.json +1 -42204
- package/src/icons/registry.ts +1 -1
|
@@ -1,74 +1,158 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Pressable,
|
|
5
|
+
type StyleProp,
|
|
6
|
+
type ViewStyle,
|
|
7
|
+
} from 'react-native'
|
|
8
|
+
import Svg, { Path, Defs, LinearGradient, Stop, ClipPath, Rect, G } from 'react-native-svg'
|
|
3
9
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
10
|
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
5
|
-
|
|
6
11
|
import NavArrow from '../NavArrow/NavArrow'
|
|
7
12
|
import { cloneChildrenWithModes, EMPTY_MODES } from '../../utils/react-utils'
|
|
8
13
|
import type { Modes } from '../../design-tokens'
|
|
9
14
|
|
|
10
15
|
type AppBarType = 'MainPage' | 'SubPage'
|
|
11
16
|
|
|
12
|
-
// SubPage "slot wrap" geometry
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// item so it fills / shrinks responsively within that box.
|
|
17
|
+
// SubPage "slot wrap" geometry from Figma (node 449:7876). The middle slot is
|
|
18
|
+
// an absolutely-centered fixed-size box; its inner content (node 3991:4125)
|
|
19
|
+
// fills / shrinks responsively within that box.
|
|
16
20
|
const SUBPAGE_MIDDLE_DEFAULT_WIDTH = 192
|
|
17
21
|
const SUBPAGE_MIDDLE_HEIGHT = 32
|
|
18
22
|
const SUBPAGE_MIDDLE_PADDING_HORIZONTAL = 21
|
|
23
|
+
const JIODOT_FALLBACK_SIZE = 32
|
|
24
|
+
|
|
25
|
+
export type JioDotProps = {
|
|
26
|
+
/** Render size in px. Defaults to token `appBar/mainPage/jiodot/size` (32). */
|
|
27
|
+
size?: number
|
|
28
|
+
/** Modes used to resolve `appBar/mainPage/jiodot/size` when `size` is omitted. */
|
|
29
|
+
modes?: Modes
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Figma "jiodot" mark (node 1117:1908). Opt-in via `leadingSlot` — MainPage
|
|
34
|
+
* does NOT render this by default so existing consumers stay empty-leading.
|
|
35
|
+
*/
|
|
36
|
+
export function JioDot({ size, modes = EMPTY_MODES }: JioDotProps) {
|
|
37
|
+
const resolvedSize =
|
|
38
|
+
size ??
|
|
39
|
+
(Number(getVariableByName('appBar/mainPage/jiodot/size', modes)) ||
|
|
40
|
+
JIODOT_FALLBACK_SIZE)
|
|
41
|
+
return (
|
|
42
|
+
<Svg
|
|
43
|
+
width={resolvedSize}
|
|
44
|
+
height={resolvedSize}
|
|
45
|
+
viewBox="0 0 32 32"
|
|
46
|
+
fill="none"
|
|
47
|
+
accessibilityRole="image"
|
|
48
|
+
accessibilityLabel="Jio"
|
|
49
|
+
>
|
|
50
|
+
<G clipPath="url(#jiodotClip)">
|
|
51
|
+
<Path
|
|
52
|
+
d="M0 16C0 7.16344 7.16344 0 16 0C24.8366 0 32 7.16344 32 16C32 24.8366 24.8366 32 16 32C7.16344 32 0 24.8366 0 16Z"
|
|
53
|
+
fill="url(#jiodotGrad)"
|
|
54
|
+
/>
|
|
55
|
+
<Path
|
|
56
|
+
d="M11.3039 9.64982H10.7705C9.75837 9.64982 9.20548 10.2205 9.20548 11.3621V16.8679C9.20548 18.2854 8.72667 18.7829 7.60341 18.7829C6.71985 18.7829 6.00192 18.3959 5.43096 17.6963C5.37555 17.6229 4.21615 18.1749 4.21615 19.5378C4.21615 21.0107 5.59629 21.9132 8.15689 21.9132C11.268 21.9132 12.9077 20.3479 12.9077 16.9233V11.3621C12.9059 10.222 12.3536 9.64982 11.3039 9.64982ZM23.7039 12.3381C20.6837 12.3381 18.6769 14.2531 18.6769 17.1085C18.6769 20.0365 20.6096 21.915 23.6482 21.915C26.6674 21.915 28.6556 20.0365 28.6556 17.1274C28.6573 14.2531 26.6867 12.3381 23.7039 12.3381ZM23.6668 19.206C22.4879 19.206 21.6781 18.3408 21.6781 17.107C21.6781 15.8922 22.5077 15.0264 23.6668 15.0264C24.8259 15.0264 25.6553 15.8922 25.6553 17.1257C25.6556 18.3221 24.8084 19.206 23.6668 19.206ZM16.1252 12.43H15.7563C14.8547 12.43 14.1735 12.8531 14.1735 14.1426V20.0347C14.1735 21.3423 14.8366 21.7476 15.7936 21.7476H16.1622C17.0644 21.7476 17.7086 21.3052 17.7086 20.0347V14.1426C17.7086 12.8169 17.0831 12.43 16.1252 12.43ZM15.9228 8.15885C14.7809 8.15885 14.063 8.80359 14.063 9.81634C14.063 10.8469 14.7999 11.4913 15.9779 11.4913C17.1196 11.4913 17.8378 10.8469 17.8378 9.81634C17.8378 8.78582 17.1012 8.15885 15.9228 8.15885Z"
|
|
57
|
+
fill="white"
|
|
58
|
+
/>
|
|
59
|
+
</G>
|
|
60
|
+
<Defs>
|
|
61
|
+
<LinearGradient
|
|
62
|
+
id="jiodotGrad"
|
|
63
|
+
x1="11.085"
|
|
64
|
+
y1="9.25442"
|
|
65
|
+
x2="22.3469"
|
|
66
|
+
y2="15.7638"
|
|
67
|
+
gradientUnits="userSpaceOnUse"
|
|
68
|
+
>
|
|
69
|
+
<Stop stopColor="#FBDCAF" />
|
|
70
|
+
<Stop offset="1" stopColor="#AD8444" />
|
|
71
|
+
</LinearGradient>
|
|
72
|
+
<ClipPath id="jiodotClip">
|
|
73
|
+
<Rect width="32" height="32" fill="white" />
|
|
74
|
+
</ClipPath>
|
|
75
|
+
</Defs>
|
|
76
|
+
</Svg>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
19
79
|
|
|
20
80
|
export type AppBarProps = {
|
|
21
81
|
/**
|
|
22
82
|
* Type of the App Bar.
|
|
23
|
-
* - `MainPage`: Taller
|
|
24
|
-
* - `SubPage`: Shorter
|
|
83
|
+
* - `MainPage`: Taller bar; no default leading (pass `JioDot` or your logo via `leadingSlot`).
|
|
84
|
+
* - `SubPage`: Shorter bar with default back arrow and centered middle slot.
|
|
25
85
|
* @default "MainPage"
|
|
26
86
|
*/
|
|
27
|
-
type?: AppBarType
|
|
87
|
+
type?: AppBarType
|
|
28
88
|
/**
|
|
29
89
|
* Slot for the leading element.
|
|
30
90
|
* Defaults:
|
|
31
|
-
* - MainPage:
|
|
32
|
-
* - SubPage: Back
|
|
91
|
+
* - MainPage: none (opt in with `<JioDot />` or any custom node)
|
|
92
|
+
* - SubPage: Back `NavArrow`
|
|
33
93
|
*/
|
|
34
|
-
leadingSlot?: React.ReactNode
|
|
94
|
+
leadingSlot?: React.ReactNode
|
|
35
95
|
/**
|
|
36
|
-
* Slot for the middle content.
|
|
37
|
-
* Often used for "Page Title" in SubPage.
|
|
96
|
+
* Slot for the middle content. Often used for a page title on SubPage.
|
|
38
97
|
*
|
|
39
|
-
* On `SubPage` this is rendered as an absolutely-centered box (
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* within {@link middleSlotWidth}.
|
|
98
|
+
* On `SubPage` this is rendered as an absolutely-centered box (Figma
|
|
99
|
+
* "slot wrap"): it stays centered regardless of leading/actions width, and
|
|
100
|
+
* content fills/shrinks within {@link middleSlotWidth}.
|
|
43
101
|
*/
|
|
44
|
-
middleSlot?: React.ReactNode
|
|
102
|
+
middleSlot?: React.ReactNode
|
|
45
103
|
/**
|
|
46
104
|
* Width of the centered `SubPage` middle slot, in px.
|
|
47
105
|
* Defaults to the Figma value (192). Has no effect on `MainPage`.
|
|
48
106
|
* @default 192
|
|
49
107
|
*/
|
|
50
|
-
middleSlotWidth?: number
|
|
108
|
+
middleSlotWidth?: number
|
|
51
109
|
/**
|
|
52
|
-
* Slot for the actions on the right.
|
|
110
|
+
* Slot for the actions on the right (IconButtons, Avatar, etc.).
|
|
53
111
|
*/
|
|
54
|
-
actionsSlot?: React.ReactNode
|
|
112
|
+
actionsSlot?: React.ReactNode
|
|
55
113
|
/**
|
|
56
114
|
* Token modes to override.
|
|
57
115
|
*/
|
|
58
|
-
modes?: Modes
|
|
116
|
+
modes?: Modes
|
|
59
117
|
/**
|
|
60
|
-
* Callback for the default leading
|
|
118
|
+
* Callback for the default SubPage leading back arrow.
|
|
61
119
|
*/
|
|
62
|
-
onLeadingPress?: () => void
|
|
120
|
+
onLeadingPress?: () => void
|
|
63
121
|
/**
|
|
64
122
|
* Container style override.
|
|
65
123
|
*/
|
|
66
|
-
style?: StyleProp<ViewStyle
|
|
67
|
-
accessibilityLabel?: string
|
|
68
|
-
accessibilityHint?: string
|
|
69
|
-
} & Omit<
|
|
124
|
+
style?: StyleProp<ViewStyle>
|
|
125
|
+
accessibilityLabel?: string
|
|
126
|
+
accessibilityHint?: string
|
|
127
|
+
} & Omit<
|
|
128
|
+
React.ComponentProps<typeof View>,
|
|
129
|
+
'style' | 'accessibilityRole' | 'accessibilityLabel' | 'accessibilityHint'
|
|
130
|
+
>
|
|
70
131
|
|
|
71
|
-
|
|
132
|
+
/**
|
|
133
|
+
* AppBar — top navigation bar for MainPage and SubPage layouts
|
|
134
|
+
* (Figma node 1070:18571).
|
|
135
|
+
*
|
|
136
|
+
* Visual values resolve from design tokens via `getVariableByName`. Slots
|
|
137
|
+
* cascade `modes` to children through `cloneChildrenWithModes`.
|
|
138
|
+
*
|
|
139
|
+
* @component
|
|
140
|
+
* @example
|
|
141
|
+
* ```tsx
|
|
142
|
+
* <AppBar
|
|
143
|
+
* type="MainPage"
|
|
144
|
+
* leadingSlot={<JioDot />}
|
|
145
|
+
* actionsSlot={
|
|
146
|
+
* <>
|
|
147
|
+
* <IconButton iconName="ic_add" />
|
|
148
|
+
* <IconButton iconName="ic_add" />
|
|
149
|
+
* <Avatar />
|
|
150
|
+
* </>
|
|
151
|
+
* }
|
|
152
|
+
* />
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
function AppBar({
|
|
72
156
|
type = 'MainPage',
|
|
73
157
|
leadingSlot,
|
|
74
158
|
middleSlot,
|
|
@@ -82,14 +166,14 @@ export default function AppBar({
|
|
|
82
166
|
...rest
|
|
83
167
|
}: AppBarProps) {
|
|
84
168
|
const { modes: globalModes } = useTokens()
|
|
85
|
-
const modes =
|
|
169
|
+
const modes = useMemo(
|
|
170
|
+
() => ({ Context2: 'AppBar', ...globalModes, ...propModes }),
|
|
171
|
+
[globalModes, propModes]
|
|
172
|
+
)
|
|
86
173
|
|
|
87
174
|
const isMain = type === 'MainPage'
|
|
88
175
|
const isSub = type === 'SubPage'
|
|
89
176
|
|
|
90
|
-
// --- Tokens ---
|
|
91
|
-
// Construct token keys based on type. keys must be camelCase as per instruction.
|
|
92
|
-
// We use explicit string literals so that the extraction script can find them.
|
|
93
177
|
const paddingHorizontal = isMain
|
|
94
178
|
? getVariableByName('appBar/mainPage/padding/horizontal', modes)
|
|
95
179
|
: getVariableByName('appBar/subPage/padding/horizontal', modes)
|
|
@@ -106,61 +190,35 @@ export default function AppBar({
|
|
|
106
190
|
? getVariableByName('appBar/mainPage/actions/gap', modes)
|
|
107
191
|
: getVariableByName('appBar/subPage/actions/gap', modes)
|
|
108
192
|
|
|
109
|
-
// Layout styles
|
|
110
193
|
const containerStyle: ViewStyle = {
|
|
111
194
|
flexDirection: 'row',
|
|
112
195
|
alignItems: 'center',
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// level so leading & actions still anchor to the edges.
|
|
117
|
-
paddingHorizontal: paddingHorizontal ?? 16,
|
|
118
|
-
paddingVertical: paddingVertical ?? (isMain ? 16 : 10),
|
|
119
|
-
backgroundColor: backgroundColor ?? '#FFFFFF',
|
|
120
|
-
// MainPage: h=68 (16 top/bot padding? 36 height content?)
|
|
121
|
-
// SubPage: h=52
|
|
196
|
+
paddingHorizontal: (paddingHorizontal as number) ?? 16,
|
|
197
|
+
paddingVertical: (paddingVertical as number) ?? (isMain ? 16 : 10),
|
|
198
|
+
backgroundColor: (backgroundColor as string) ?? '#FFFFFF',
|
|
122
199
|
}
|
|
123
200
|
|
|
124
|
-
//
|
|
125
|
-
// SubPage default
|
|
126
|
-
// MainPage default: Jio Logo (We'll use a placeholder or basic text if no asset,
|
|
127
|
-
// but looking at "AppBarHome" before, it had "ic_hellojio". Let's stick to generic defaults or empty if not provided,
|
|
128
|
-
// but usually a component library provides sensible defaults.)
|
|
129
|
-
|
|
130
|
-
// Actually, let's implement the specific defaults mentioned in the plan/analysis
|
|
131
|
-
// SubPage: NavArrow props (icon, etc).
|
|
132
|
-
|
|
201
|
+
// MainPage: no default leading (backward compatible — consumers opt in via
|
|
202
|
+
// leadingSlot, e.g. <JioDot />). SubPage: default back NavArrow.
|
|
133
203
|
let defaultLeading: React.ReactNode = null
|
|
134
|
-
if (leadingSlot === undefined) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
151
|
-
} else {
|
|
152
|
-
// MainPage default leading: often the Brand Logo.
|
|
153
|
-
// We'll leave it empty or render a placeholder if desired, but standard AppBar often lets consumer pass logo.
|
|
154
|
-
// Previous code had `leadingIconName='ic_hellojio'` for Home.
|
|
155
|
-
// We will render nothing by default for MainPage leading to keep it flexible, OR a specialized Logo component if we had one.
|
|
156
|
-
// For now, let's assume consumer passes it for MainPage, or we leave empty.
|
|
157
|
-
// Wait, Figma screenshot shows "Jio" logo.
|
|
158
|
-
// The user said: "mostly token namings are 'camelCase'. Maximize existing component usage."
|
|
159
|
-
// I'll leave defaultLeading as null for MainPage unless I have a "BrandLogo" component.
|
|
160
|
-
}
|
|
204
|
+
if (leadingSlot === undefined && isSub) {
|
|
205
|
+
defaultLeading = (
|
|
206
|
+
<Pressable
|
|
207
|
+
{...(onLeadingPress ? { onPress: onLeadingPress } : {})}
|
|
208
|
+
hitSlop={8}
|
|
209
|
+
accessibilityRole="button"
|
|
210
|
+
accessibilityLabel={undefined}
|
|
211
|
+
style={({ pressed }) => ({
|
|
212
|
+
opacity: pressed ? 0.7 : 1,
|
|
213
|
+
alignItems: 'center',
|
|
214
|
+
justifyContent: 'center',
|
|
215
|
+
})}
|
|
216
|
+
>
|
|
217
|
+
<NavArrow direction="Back" modes={modes} />
|
|
218
|
+
</Pressable>
|
|
219
|
+
)
|
|
161
220
|
}
|
|
162
221
|
|
|
163
|
-
// --- Process Slots ---
|
|
164
222
|
const processedLeading = leadingSlot
|
|
165
223
|
? cloneChildrenWithModes([leadingSlot], modes)[0]
|
|
166
224
|
: defaultLeading
|
|
@@ -169,40 +227,28 @@ export default function AppBar({
|
|
|
169
227
|
? cloneChildrenWithModes(React.Children.toArray(middleSlot), modes)
|
|
170
228
|
: null
|
|
171
229
|
|
|
172
|
-
// Actions Gap wrapper
|
|
173
|
-
// The Figma has "Actions" slot with a gap.
|
|
174
230
|
const actionsStyle: ViewStyle = {
|
|
175
231
|
flexDirection: 'row',
|
|
176
232
|
alignItems: 'center',
|
|
177
|
-
gap: actionsGap ?? 0,
|
|
233
|
+
gap: (actionsGap as number) ?? 0,
|
|
178
234
|
}
|
|
179
235
|
|
|
180
236
|
const processedActions = actionsSlot
|
|
181
|
-
?
|
|
237
|
+
? cloneChildrenWithModes(React.Children.toArray(actionsSlot), modes)
|
|
182
238
|
: null
|
|
183
239
|
|
|
184
|
-
// SubPage
|
|
185
|
-
// "slot wrap"), so it never participates in the row flow. Only MainPage
|
|
186
|
-
// keeps the legacy in-flow middle slot.
|
|
240
|
+
// SubPage middle is absolute (Figma "slot wrap"); MainPage middle stays in-flow.
|
|
187
241
|
const hasInFlowMiddle = isMain && !!processedMiddle
|
|
188
242
|
|
|
189
|
-
// With an in-flow middle
|
|
190
|
-
//
|
|
191
|
-
// other cases we pin leading & actions to the outer edges with
|
|
192
|
-
// `space-between`; the SubPage middle floats above, centered.
|
|
243
|
+
// With an in-flow middle the flex:1 middle absorbs leftover space. Otherwise
|
|
244
|
+
// pin leading & actions to the edges; SubPage middle floats centered above.
|
|
193
245
|
const wrapperStyle: ViewStyle = {
|
|
194
246
|
...containerStyle,
|
|
195
247
|
justifyContent: hasInFlowMiddle ? 'flex-start' : 'space-between',
|
|
196
248
|
}
|
|
197
249
|
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// Android resolves the percentage against an intermediate, content-driven
|
|
201
|
-
// parent height and lands a few px too high), the overlay STRETCHES to fill
|
|
202
|
-
// the whole bar (`top/bottom/left/right: 0`) and centers its content with
|
|
203
|
-
// flexbox. This uses the exact same full-height vertical reference as the
|
|
204
|
-
// leading/actions row (`alignItems: 'center'`), so the middle content always
|
|
205
|
-
// sits on the same line as the back arrow and end slot on every platform.
|
|
250
|
+
// Overlay stretches to the full bar and centers content with flexbox so the
|
|
251
|
+
// middle aligns with leading/actions on every platform.
|
|
206
252
|
const subPageMiddleOverlayStyle: ViewStyle = {
|
|
207
253
|
position: 'absolute',
|
|
208
254
|
top: 0,
|
|
@@ -214,9 +260,6 @@ export default function AppBar({
|
|
|
214
260
|
justifyContent: 'center',
|
|
215
261
|
}
|
|
216
262
|
|
|
217
|
-
// Fixed-width clipping box (mirrors the Figma "slot wrap" geometry): keeps the
|
|
218
|
-
// middle content from bleeding under the leading/actions slots while staying
|
|
219
|
-
// centered within the overlay above.
|
|
220
263
|
const subPageMiddleBoxStyle: ViewStyle = {
|
|
221
264
|
width: middleSlotWidth,
|
|
222
265
|
height: SUBPAGE_MIDDLE_HEIGHT,
|
|
@@ -235,18 +278,11 @@ export default function AppBar({
|
|
|
235
278
|
{...(accessibilityHint ? { accessibilityHint } : {})}
|
|
236
279
|
{...rest}
|
|
237
280
|
>
|
|
238
|
-
{/* Leading Section */}
|
|
239
281
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
240
282
|
{processedLeading}
|
|
241
283
|
</View>
|
|
242
284
|
|
|
243
|
-
{
|
|
244
|
-
* MainPage in-flow middle — occupies the space between leading and
|
|
245
|
-
* actions (`flex: 1`) without overflowing. `minWidth: 0` lets the flex
|
|
246
|
-
* item shrink below its content's intrinsic width on platforms that
|
|
247
|
-
* respect it (web).
|
|
248
|
-
*/}
|
|
249
|
-
{hasInFlowMiddle && (
|
|
285
|
+
{hasInFlowMiddle ? (
|
|
250
286
|
<View
|
|
251
287
|
style={{
|
|
252
288
|
flex: 1,
|
|
@@ -259,19 +295,11 @@ export default function AppBar({
|
|
|
259
295
|
>
|
|
260
296
|
{processedMiddle}
|
|
261
297
|
</View>
|
|
262
|
-
)}
|
|
298
|
+
) : null}
|
|
263
299
|
|
|
264
|
-
{
|
|
265
|
-
<View style={actionsStyle}>
|
|
266
|
-
{processedActions}
|
|
267
|
-
</View>
|
|
300
|
+
<View style={actionsStyle}>{processedActions}</View>
|
|
268
301
|
|
|
269
|
-
{
|
|
270
|
-
* SubPage middle — absolutely centered "slot wrap". The inner wrapper is
|
|
271
|
-
* a responsive `flex: 1` item (matching Figma's `flex-[1_0_0] min-w-px`)
|
|
272
|
-
* so its content fills / shrinks within the fixed-width box.
|
|
273
|
-
*/}
|
|
274
|
-
{isSub && processedMiddle && (
|
|
302
|
+
{isSub && processedMiddle ? (
|
|
275
303
|
<View style={subPageMiddleOverlayStyle} pointerEvents="box-none">
|
|
276
304
|
<View style={subPageMiddleBoxStyle} pointerEvents="box-none">
|
|
277
305
|
<View
|
|
@@ -289,7 +317,9 @@ export default function AppBar({
|
|
|
289
317
|
</View>
|
|
290
318
|
</View>
|
|
291
319
|
</View>
|
|
292
|
-
)}
|
|
320
|
+
) : null}
|
|
293
321
|
</View>
|
|
294
322
|
)
|
|
295
323
|
}
|
|
324
|
+
|
|
325
|
+
export default AppBar
|