@butternutbox/pawprint-native 0.10.3 → 0.10.5
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/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +13 -0
- package/dist/index.cjs +242 -192
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -5
- package/dist/index.d.ts +15 -5
- package/dist/index.js +242 -193
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/molecules/NumberField/NumberField.stories.tsx +19 -0
- package/src/components/molecules/NumberField/NumberField.tsx +14 -4
- package/src/components/molecules/NumberField/NumberFieldInput.tsx +10 -4
- package/src/components/molecules/ProductDisplayCard/ProductDisplayCard.stories.tsx +6 -15
- package/src/components/molecules/ProductDisplayCard/ProductDisplayCard.test.tsx +2 -3
- package/src/components/molecules/ProductDisplayCard/ProductDisplayCard.tsx +46 -12
- package/src/components/molecules/Radio/Radio.stories.tsx +64 -0
- package/src/components/molecules/Radio/Radio.tsx +10 -0
- package/src/components/molecules/Radio/RadioGroup.tsx +4 -2
- package/src/components/molecules/Radio/index.ts +1 -1
- package/src/fonts/index.ts +15 -16
package/package.json
CHANGED
|
@@ -202,6 +202,25 @@ export const Controlled = () => {
|
|
|
202
202
|
)
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
export const FullWidth = () => {
|
|
206
|
+
const [value, setValue] = useState(5)
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<View style={styles.section}>
|
|
210
|
+
<NumberField
|
|
211
|
+
label="Weight"
|
|
212
|
+
size="lg"
|
|
213
|
+
fullWidth
|
|
214
|
+
description="Help text"
|
|
215
|
+
value={String(value)}
|
|
216
|
+
onChangeText={(t) => setValue(Number(t) || 0)}
|
|
217
|
+
onIncrement={() => setValue((v) => v + 1)}
|
|
218
|
+
onDecrement={() => setValue((v) => Math.max(0, v - 1))}
|
|
219
|
+
/>
|
|
220
|
+
</View>
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
205
224
|
export const Playground = {
|
|
206
225
|
args: {
|
|
207
226
|
size: "lg",
|
|
@@ -19,6 +19,7 @@ type NumberFieldOwnProps = {
|
|
|
19
19
|
state?: NumberFieldState
|
|
20
20
|
size?: NumberFieldSize
|
|
21
21
|
disabled?: boolean
|
|
22
|
+
fullWidth?: boolean
|
|
22
23
|
onIncrement?: () => void
|
|
23
24
|
onDecrement?: () => void
|
|
24
25
|
showIncrementButton?: boolean
|
|
@@ -37,9 +38,10 @@ const parseTokenValue = (value: string): number => parseFloat(value)
|
|
|
37
38
|
|
|
38
39
|
const StyledRoot = styled(View)<{
|
|
39
40
|
rootGap: number
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
gap: rootGap
|
|
41
|
+
fullWidth?: boolean
|
|
42
|
+
}>(({ rootGap, fullWidth }) => ({
|
|
43
|
+
gap: rootGap,
|
|
44
|
+
...(fullWidth && { width: "100%" })
|
|
43
45
|
}))
|
|
44
46
|
|
|
45
47
|
const StyledLabelGroup = styled(View)<{
|
|
@@ -60,6 +62,7 @@ const StyledLabelGroup = styled(View)<{
|
|
|
60
62
|
* @param {string} [error] - Error message displayed when state is "error".
|
|
61
63
|
* @param {"default" | "error" | "success"} [state="default"] - Visual state of the field.
|
|
62
64
|
* @param {boolean} [disabled=false] - Whether the entire field (input + buttons) is disabled.
|
|
65
|
+
* @param {boolean} [fullWidth=false] - Whether the field should expand to fill available width.
|
|
63
66
|
* @param {() => void} [onIncrement] - Called when the + button is pressed.
|
|
64
67
|
* @param {() => void} [onDecrement] - Called when the - button is pressed.
|
|
65
68
|
* @param {boolean} [showIncrementButton=true] - Whether to show the + button.
|
|
@@ -76,6 +79,7 @@ const StyledLabelGroup = styled(View)<{
|
|
|
76
79
|
* <NumberField
|
|
77
80
|
* label="Weight"
|
|
78
81
|
* size="lg"
|
|
82
|
+
* fullWidth
|
|
79
83
|
* defaultValue="0"
|
|
80
84
|
* onIncrement={() => setValue(v => v + 1)}
|
|
81
85
|
* onDecrement={() => setValue(v => v - 1)}
|
|
@@ -94,6 +98,7 @@ export const NumberField = React.forwardRef<View, NumberFieldProps>(
|
|
|
94
98
|
state = "default",
|
|
95
99
|
size = "lg",
|
|
96
100
|
disabled,
|
|
101
|
+
fullWidth,
|
|
97
102
|
onIncrement,
|
|
98
103
|
onDecrement,
|
|
99
104
|
showIncrementButton,
|
|
@@ -114,7 +119,11 @@ export const NumberField = React.forwardRef<View, NumberFieldProps>(
|
|
|
114
119
|
size === "lg" ? tokens.typography.large : tokens.typography.small
|
|
115
120
|
|
|
116
121
|
return (
|
|
117
|
-
<StyledRoot
|
|
122
|
+
<StyledRoot
|
|
123
|
+
ref={ref}
|
|
124
|
+
rootGap={parseTokenValue(sizeTokens.gap)}
|
|
125
|
+
fullWidth={fullWidth}
|
|
126
|
+
>
|
|
118
127
|
{(label || smallLabel) && (
|
|
119
128
|
<StyledLabelGroup
|
|
120
129
|
labelGap={parseTokenValue(
|
|
@@ -142,6 +151,7 @@ export const NumberField = React.forwardRef<View, NumberFieldProps>(
|
|
|
142
151
|
<NumberFieldInput
|
|
143
152
|
fieldSize={size}
|
|
144
153
|
state={state}
|
|
154
|
+
fullWidth={fullWidth}
|
|
145
155
|
disabled={disabled}
|
|
146
156
|
onIncrement={onIncrement}
|
|
147
157
|
onDecrement={onDecrement}
|
|
@@ -11,6 +11,7 @@ type NumberFieldSize = "sm" | "lg"
|
|
|
11
11
|
type NumberFieldInputOwnProps = {
|
|
12
12
|
fieldSize?: NumberFieldSize
|
|
13
13
|
state?: "default" | "error" | "success"
|
|
14
|
+
fullWidth?: boolean
|
|
14
15
|
onIncrement?: () => void
|
|
15
16
|
onDecrement?: () => void
|
|
16
17
|
showIncrementButton?: boolean
|
|
@@ -34,6 +35,7 @@ const StyledFieldWrapper = styled(View)<{
|
|
|
34
35
|
fieldMinWidth: number
|
|
35
36
|
fieldHeight: number
|
|
36
37
|
fieldPaddingHorizontal: number
|
|
38
|
+
fullWidth?: boolean
|
|
37
39
|
}>(
|
|
38
40
|
({
|
|
39
41
|
fieldBgColor,
|
|
@@ -41,18 +43,21 @@ const StyledFieldWrapper = styled(View)<{
|
|
|
41
43
|
fieldBorderRadius,
|
|
42
44
|
fieldMinWidth,
|
|
43
45
|
fieldHeight,
|
|
44
|
-
fieldPaddingHorizontal
|
|
46
|
+
fieldPaddingHorizontal,
|
|
47
|
+
fullWidth
|
|
45
48
|
}) => ({
|
|
46
49
|
alignItems: "center",
|
|
47
50
|
justifyContent: "center",
|
|
48
|
-
width: fieldMinWidth,
|
|
51
|
+
width: fullWidth ? "100%" : fieldMinWidth,
|
|
52
|
+
minWidth: fieldMinWidth,
|
|
49
53
|
height: fieldHeight,
|
|
50
54
|
paddingHorizontal: fieldPaddingHorizontal,
|
|
51
55
|
backgroundColor: fieldBgColor,
|
|
52
56
|
borderWidth: 1,
|
|
53
57
|
borderColor: fieldBorderColor,
|
|
54
58
|
borderRadius: fieldBorderRadius,
|
|
55
|
-
overflow: "hidden"
|
|
59
|
+
overflow: "hidden",
|
|
60
|
+
...(fullWidth && { flex: 1 })
|
|
56
61
|
})
|
|
57
62
|
)
|
|
58
63
|
|
|
@@ -94,7 +99,6 @@ const StyledRow = styled(View)<{
|
|
|
94
99
|
}>(({ rowGap }) => ({
|
|
95
100
|
flexDirection: "row",
|
|
96
101
|
alignItems: "center",
|
|
97
|
-
alignSelf: "center",
|
|
98
102
|
gap: rowGap
|
|
99
103
|
}))
|
|
100
104
|
|
|
@@ -117,6 +121,7 @@ export const NumberFieldInput = React.forwardRef<
|
|
|
117
121
|
{
|
|
118
122
|
fieldSize = "lg",
|
|
119
123
|
state = "default",
|
|
124
|
+
fullWidth,
|
|
120
125
|
onIncrement,
|
|
121
126
|
onDecrement,
|
|
122
127
|
showIncrementButton = true,
|
|
@@ -236,6 +241,7 @@ export const NumberFieldInput = React.forwardRef<
|
|
|
236
241
|
fieldMinWidth={fieldMinWidth}
|
|
237
242
|
fieldHeight={fieldHeight}
|
|
238
243
|
fieldPaddingHorizontal={fieldPaddingHorizontal}
|
|
244
|
+
fullWidth={fullWidth}
|
|
239
245
|
>
|
|
240
246
|
<StyledTextInput
|
|
241
247
|
ref={ref}
|
|
@@ -69,12 +69,9 @@ export default {
|
|
|
69
69
|
},
|
|
70
70
|
bannerType: {
|
|
71
71
|
control: { type: "select" },
|
|
72
|
-
options: ["
|
|
73
|
-
description:
|
|
74
|
-
|
|
75
|
-
showBannerIcon: {
|
|
76
|
-
control: { type: "boolean" },
|
|
77
|
-
description: "Show/hide banner notification icon"
|
|
72
|
+
options: ["none", "error", "info"],
|
|
73
|
+
description:
|
|
74
|
+
"Banner variant: none (no icon), error (with icon), info (with icon)"
|
|
78
75
|
}
|
|
79
76
|
}
|
|
80
77
|
}
|
|
@@ -91,8 +88,7 @@ Playground.args = {
|
|
|
91
88
|
quantity: 1,
|
|
92
89
|
showQuantityPicker: true,
|
|
93
90
|
showBanner: true,
|
|
94
|
-
bannerType: "
|
|
95
|
-
showBannerIcon: false,
|
|
91
|
+
bannerType: "none",
|
|
96
92
|
banner: " High in protein • Natural ingredients • Vet approved",
|
|
97
93
|
image: placeholderImageUrl
|
|
98
94
|
}
|
|
@@ -134,8 +130,6 @@ export const WithBanner = () => (
|
|
|
134
130
|
quantity={1}
|
|
135
131
|
showQuantityPicker
|
|
136
132
|
showBanner
|
|
137
|
-
bannerType="success"
|
|
138
|
-
showBannerIcon={false}
|
|
139
133
|
banner="High in protein • Natural ingredients • Vet approved"
|
|
140
134
|
image={placeholderImageUrl}
|
|
141
135
|
/>
|
|
@@ -151,8 +145,7 @@ export const WithBannerIcon = () => (
|
|
|
151
145
|
quantity={1}
|
|
152
146
|
showQuantityPicker
|
|
153
147
|
showBanner
|
|
154
|
-
bannerType="
|
|
155
|
-
showBannerIcon
|
|
148
|
+
bannerType="info"
|
|
156
149
|
banner="High in protein • Natural ingredients • Vet approved"
|
|
157
150
|
image={placeholderImageUrl}
|
|
158
151
|
/>
|
|
@@ -217,8 +210,6 @@ export const WithMinQuantity = () => (
|
|
|
217
210
|
minQuantity={5}
|
|
218
211
|
showQuantityPicker
|
|
219
212
|
showBanner
|
|
220
|
-
bannerType="info"
|
|
221
|
-
showBannerIcon={false}
|
|
222
213
|
banner="Minimum quantity: 5 pouches required"
|
|
223
214
|
image={placeholderImageUrl}
|
|
224
215
|
/>
|
|
@@ -237,7 +228,7 @@ export const WithImagePress = () => {
|
|
|
237
228
|
showQuantityPicker
|
|
238
229
|
onImagePress={() => setPressed(true)}
|
|
239
230
|
showBanner={pressed}
|
|
240
|
-
bannerType="
|
|
231
|
+
bannerType="info"
|
|
241
232
|
banner="Image pressed!"
|
|
242
233
|
image={placeholderImageUrl}
|
|
243
234
|
/>
|
|
@@ -159,7 +159,6 @@ describe("ProductDisplayCard (Native)", () => {
|
|
|
159
159
|
title="Test Product"
|
|
160
160
|
showBanner={true}
|
|
161
161
|
banner={<Text>Test Banner</Text>}
|
|
162
|
-
bannerType="success"
|
|
163
162
|
/>
|
|
164
163
|
)
|
|
165
164
|
|
|
@@ -177,13 +176,13 @@ describe("ProductDisplayCard (Native)", () => {
|
|
|
177
176
|
expect(screen.getByText("Error Banner")).toBeTruthy()
|
|
178
177
|
})
|
|
179
178
|
|
|
180
|
-
it("displays banner with icon when
|
|
179
|
+
it("displays banner with icon when bannerType is info", () => {
|
|
181
180
|
renderWithTheme(
|
|
182
181
|
<ProductDisplayCard
|
|
183
182
|
title="Test Product"
|
|
184
183
|
showBanner={true}
|
|
184
|
+
bannerType="info"
|
|
185
185
|
banner={<Text>Test Banner</Text>}
|
|
186
|
-
showBannerIcon={true}
|
|
187
186
|
/>
|
|
188
187
|
)
|
|
189
188
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import { View, ViewProps, Image, Pressable } from "react-native"
|
|
3
3
|
import styled from "@emotion/native"
|
|
4
|
+
import { useTheme } from "@emotion/react"
|
|
4
5
|
import { Typography } from "../../atoms/Typography"
|
|
5
6
|
import { NumberField } from "../../molecules/NumberField"
|
|
6
7
|
import { Notification } from "../Notification"
|
|
@@ -24,7 +25,7 @@ export type ProductDisplayCardProps = ViewProps & {
|
|
|
24
25
|
onImagePress?: () => void
|
|
25
26
|
banner?: string | React.ReactNode
|
|
26
27
|
showBanner?: boolean
|
|
27
|
-
bannerType?: "error" | "
|
|
28
|
+
bannerType?: "error" | "info" | "none"
|
|
28
29
|
showBannerIcon?: boolean
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -132,6 +133,23 @@ const StyledNotification = styled(Notification as any)(({ theme }) => {
|
|
|
132
133
|
}
|
|
133
134
|
})
|
|
134
135
|
|
|
136
|
+
const StyledNoneBanner = styled(View)(({ theme }) => {
|
|
137
|
+
const { spacing, borderRadius } = theme.tokens.semantics.dimensions
|
|
138
|
+
const { colour } = theme.tokens.semantics
|
|
139
|
+
const spacingMd = parseTokenValue(spacing.md)
|
|
140
|
+
const radiusMd = parseTokenValue(borderRadius.md)
|
|
141
|
+
return {
|
|
142
|
+
paddingHorizontal: spacingMd,
|
|
143
|
+
paddingTop: 27,
|
|
144
|
+
paddingBottom: spacingMd,
|
|
145
|
+
backgroundColor: colour.background.container.secondary,
|
|
146
|
+
borderTopLeftRadius: 0,
|
|
147
|
+
borderTopRightRadius: 0,
|
|
148
|
+
borderBottomLeftRadius: radiusMd,
|
|
149
|
+
borderBottomRightRadius: radiusMd
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
|
|
135
153
|
/**
|
|
136
154
|
* Product Display Card component for showing product information with optional quantity picker.
|
|
137
155
|
*
|
|
@@ -156,8 +174,8 @@ const StyledNotification = styled(Notification as any)(({ theme }) => {
|
|
|
156
174
|
* @param image - *(optional)* Image URL string or React element
|
|
157
175
|
* @param banner - *(optional)* Banner content string or React element to show below card
|
|
158
176
|
* @param showBanner - *(optional)* Show/hide banner
|
|
159
|
-
* @param bannerType - *(optional)* Banner
|
|
160
|
-
* @param showBannerIcon - *(optional)* Show/hide banner
|
|
177
|
+
* @param bannerType - *(optional)* Banner variant: "error" (with icon), "info" (with icon), or "none" (no icon, default)
|
|
178
|
+
* @param showBannerIcon - *(optional)* Show/hide icon in banner (default: true)
|
|
161
179
|
*/
|
|
162
180
|
export const ProductDisplayCard = React.forwardRef<
|
|
163
181
|
View,
|
|
@@ -182,8 +200,8 @@ export const ProductDisplayCard = React.forwardRef<
|
|
|
182
200
|
onImagePress,
|
|
183
201
|
banner,
|
|
184
202
|
showBanner = false,
|
|
185
|
-
bannerType = "
|
|
186
|
-
showBannerIcon =
|
|
203
|
+
bannerType = "none",
|
|
204
|
+
showBannerIcon = true,
|
|
187
205
|
...rest
|
|
188
206
|
},
|
|
189
207
|
ref
|
|
@@ -260,17 +278,33 @@ export const ProductDisplayCard = React.forwardRef<
|
|
|
260
278
|
)
|
|
261
279
|
|
|
262
280
|
if (showBanner && banner) {
|
|
281
|
+
const theme = useTheme()
|
|
282
|
+
const { notifications } = theme.tokens.components
|
|
283
|
+
const notificationTypography = notifications.typography.body
|
|
284
|
+
const notificationColour = notifications.notification.colour.text.body
|
|
285
|
+
|
|
263
286
|
return (
|
|
264
287
|
<StyledRootWrapper>
|
|
265
288
|
{cardContent}
|
|
266
289
|
<StyledBannerWrapper>
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
290
|
+
{bannerType === "none" ? (
|
|
291
|
+
<StyledNoneBanner>
|
|
292
|
+
<Typography
|
|
293
|
+
token={notificationTypography}
|
|
294
|
+
color={notificationColour}
|
|
295
|
+
>
|
|
296
|
+
{banner}
|
|
297
|
+
</Typography>
|
|
298
|
+
</StyledNoneBanner>
|
|
299
|
+
) : (
|
|
300
|
+
<StyledNotification
|
|
301
|
+
variant="inline"
|
|
302
|
+
type={bannerType}
|
|
303
|
+
showIcon={showBannerIcon}
|
|
304
|
+
>
|
|
305
|
+
{banner}
|
|
306
|
+
</StyledNotification>
|
|
307
|
+
)}
|
|
274
308
|
</StyledBannerWrapper>
|
|
275
309
|
</StyledRootWrapper>
|
|
276
310
|
)
|
|
@@ -187,6 +187,70 @@ export const CompoundComponents = () => (
|
|
|
187
187
|
</View>
|
|
188
188
|
)
|
|
189
189
|
|
|
190
|
+
export const CompoundTiles = () => (
|
|
191
|
+
<View style={styles.column}>
|
|
192
|
+
<View style={styles.section}>
|
|
193
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
194
|
+
Basic tiles
|
|
195
|
+
</Typography>
|
|
196
|
+
<RadioGroup name="compound-tiles" defaultValue="medium">
|
|
197
|
+
<RadioGroup.Tile value="small" label="Small" subText="For tiny dogs" />
|
|
198
|
+
<RadioGroup.Tile
|
|
199
|
+
value="medium"
|
|
200
|
+
label="Medium"
|
|
201
|
+
subText="For medium dogs"
|
|
202
|
+
/>
|
|
203
|
+
<RadioGroup.Tile value="large" label="Large" subText="For big dogs" />
|
|
204
|
+
</RadioGroup>
|
|
205
|
+
</View>
|
|
206
|
+
|
|
207
|
+
<View style={styles.section}>
|
|
208
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
209
|
+
Tiles with tags
|
|
210
|
+
</Typography>
|
|
211
|
+
<RadioGroup name="tiles-with-tags" defaultValue="1">
|
|
212
|
+
<RadioGroup.Tile
|
|
213
|
+
value="1"
|
|
214
|
+
label="1 pouch over 2 days"
|
|
215
|
+
subText="400g pouches"
|
|
216
|
+
tag={{ children: "Save up to £12.20 per box" }}
|
|
217
|
+
/>
|
|
218
|
+
<RadioGroup.Tile
|
|
219
|
+
value="2"
|
|
220
|
+
label="1 pouch per day"
|
|
221
|
+
subText="200g pouches"
|
|
222
|
+
tag={{ children: "Most popular", variant: "promo" }}
|
|
223
|
+
/>
|
|
224
|
+
<RadioGroup.Tile
|
|
225
|
+
value="3"
|
|
226
|
+
label="Custom frequency"
|
|
227
|
+
subText="Choose your own schedule"
|
|
228
|
+
/>
|
|
229
|
+
</RadioGroup>
|
|
230
|
+
</View>
|
|
231
|
+
|
|
232
|
+
<View style={styles.section}>
|
|
233
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
234
|
+
Tiles with icons and tags
|
|
235
|
+
</Typography>
|
|
236
|
+
<RadioGroup name="tiles-with-icons" defaultValue="1">
|
|
237
|
+
<RadioGroup.Tile
|
|
238
|
+
value="1"
|
|
239
|
+
label="Most popular"
|
|
240
|
+
subText="Recommended for most dogs"
|
|
241
|
+
tag={{ children: "Best value", variant: "promo", icon: StarRate }}
|
|
242
|
+
/>
|
|
243
|
+
<RadioGroup.Tile
|
|
244
|
+
value="2"
|
|
245
|
+
label="Flexible plan"
|
|
246
|
+
subText="Change anytime"
|
|
247
|
+
tag={{ children: "New", variant: "success" }}
|
|
248
|
+
/>
|
|
249
|
+
</RadioGroup>
|
|
250
|
+
</View>
|
|
251
|
+
</View>
|
|
252
|
+
)
|
|
253
|
+
|
|
190
254
|
export const Controlled = () => {
|
|
191
255
|
const [value, setValue] = useState("chicken")
|
|
192
256
|
|
|
@@ -264,3 +264,13 @@ export const Radio = React.forwardRef<View, RadioProps>(
|
|
|
264
264
|
)
|
|
265
265
|
|
|
266
266
|
Radio.displayName = "Radio"
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* RadioTile component for tile-variant radio buttons.
|
|
270
|
+
* Convenience wrapper around Radio with variant="tile" preset.
|
|
271
|
+
*/
|
|
272
|
+
export const RadioTile = React.forwardRef<View, Omit<RadioProps, "variant">>(
|
|
273
|
+
(props, ref) => <Radio ref={ref} {...props} variant="tile" />
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
RadioTile.displayName = "RadioTile"
|
|
@@ -2,7 +2,7 @@ import React from "react"
|
|
|
2
2
|
import { View, ViewProps } from "react-native"
|
|
3
3
|
import styled from "@emotion/native"
|
|
4
4
|
import { useTheme } from "@emotion/react"
|
|
5
|
-
import { Radio, type RadioOwnProps } from "./Radio"
|
|
5
|
+
import { Radio, RadioTile, type RadioOwnProps } from "./Radio"
|
|
6
6
|
|
|
7
7
|
type RadioGroupOwnProps = {
|
|
8
8
|
name: string
|
|
@@ -135,8 +135,10 @@ type RadioGroupComponent = React.ForwardRefExoticComponent<
|
|
|
135
135
|
RadioGroupProps & React.RefAttributes<View>
|
|
136
136
|
> & {
|
|
137
137
|
Radio: typeof Radio
|
|
138
|
+
Tile: typeof RadioTile
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
export const RadioGroup = Object.assign(RadioGroupRoot, {
|
|
141
|
-
Radio
|
|
142
|
+
Radio,
|
|
143
|
+
Tile: RadioTile
|
|
142
144
|
}) as RadioGroupComponent
|
package/src/fonts/index.ts
CHANGED
|
@@ -14,29 +14,28 @@ export const BRAND_FONTS: Partial<
|
|
|
14
14
|
Record<BrandName, Record<string, FontSource>>
|
|
15
15
|
> = {
|
|
16
16
|
[Brand.Butternutbox]: {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
17
|
+
"IdaWebNarrow-Medium": idaNarrow500 as FontSource,
|
|
18
|
+
"IdaWebNarrow-Bold": idaNarrow700 as FontSource,
|
|
19
|
+
"IBMPlexSansCond-Regular": ibmPlexSansCondensed400 as FontSource,
|
|
20
|
+
"IBMPlexSansCond-Medium": ibmPlexSansCondensed500 as FontSource,
|
|
21
|
+
"IBMPlexSansCond-SemiBold": ibmPlexSansCondensed600 as FontSource,
|
|
22
|
+
"IBMPlexSansCond-Bold": ibmPlexSansCondensed700 as FontSource
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// Maps token fontFamily + fontWeight →
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// fontWeight is dropped because the weight is already encoded in the key name.
|
|
26
|
+
// Maps token fontFamily + fontWeight → PostScript font name.
|
|
27
|
+
// Keys must match the PostScript name embedded in the font file — iOS registers
|
|
28
|
+
// fonts under their PostScript name regardless of the useFonts key.
|
|
30
29
|
const FONT_MAP: Record<string, Record<string, string>> = {
|
|
31
30
|
"IBM Plex Sans Condensed": {
|
|
32
|
-
"400": "
|
|
33
|
-
"500": "
|
|
34
|
-
"600": "
|
|
35
|
-
"700": "
|
|
31
|
+
"400": "IBMPlexSansCond-Regular",
|
|
32
|
+
"500": "IBMPlexSansCond-Medium",
|
|
33
|
+
"600": "IBMPlexSansCond-SemiBold",
|
|
34
|
+
"700": "IBMPlexSansCond-Bold"
|
|
36
35
|
},
|
|
37
36
|
"Ida Narrow": {
|
|
38
|
-
"500": "
|
|
39
|
-
"700": "
|
|
37
|
+
"500": "IdaWebNarrow-Medium",
|
|
38
|
+
"700": "IdaWebNarrow-Bold"
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
|