@expokit/cli 0.3.0 → 0.4.0
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/README.md +8 -4
- package/bin/expo-kit.js +137 -24
- package/bin/lib.mjs +110 -1
- package/bin/mcp.mjs +40 -18
- package/package.json +2 -2
- package/registry/_docs/assistant-app.json +47 -0
- package/registry/_docs/avatar.json +1 -1
- package/registry/_docs/badge.json +1 -1
- package/registry/_docs/bottom-nav.json +6 -6
- package/registry/_docs/button-3d.json +2 -2
- package/registry/_docs/calendar.json +5 -5
- package/registry/_docs/checkout.json +7 -1
- package/registry/_docs/confetti.json +3 -3
- package/registry/_docs/date-picker.json +4 -4
- package/registry/_docs/donut-shop.json +88 -0
- package/registry/_docs/drawer.json +4 -4
- package/registry/_docs/fintech-app.json +49 -0
- package/registry/_docs/floating-input.json +5 -5
- package/registry/_docs/food-app.json +47 -0
- package/registry/_docs/glass.json +1 -1
- package/registry/_docs/grain.json +80 -0
- package/registry/_docs/morphing-button-group.json +96 -0
- package/registry/_docs/orb-reveal.json +132 -0
- package/registry/_docs/otp-input.json +4 -4
- package/registry/_docs/password-input.json +3 -3
- package/registry/_docs/qr-code-button.json +122 -0
- package/registry/_docs/search-bar.json +3 -3
- package/registry/_docs/select.json +7 -7
- package/registry/_docs/settings.json +6 -0
- package/registry/_docs/skeleton.json +2 -2
- package/registry/_docs/slider.json +6 -6
- package/registry/_docs/spinner.json +1 -1
- package/registry/_docs/stepper.json +7 -7
- package/registry/_docs/textarea.json +2 -2
- package/registry/_docs/ticket-shape.json +1 -1
- package/registry/_docs/tilt-card.json +4 -4
- package/registry/_docs/time-picker.json +6 -6
- package/registry/_docs/timeline.json +2 -2
- package/registry/_docs/toast.json +8 -8
- package/registry/accordion/files/src/components/ui/accordion.tsx +5 -4
- package/registry/accordion/files/src/lib/kit.tsx +8 -5
- package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +9 -8
- package/registry/action-sheet/files/src/lib/kit.tsx +8 -5
- package/registry/alert/files/src/components/ui/alert.tsx +7 -4
- package/registry/alert/files/src/components/ui/button.tsx +4 -3
- package/registry/alert/files/src/lib/kit.tsx +8 -5
- package/registry/assistant-app.json +49 -0
- package/registry/avatar/files/src/components/ui/avatar.tsx +7 -4
- package/registry/avatar/files/src/lib/kit.tsx +8 -5
- package/registry/badge/files/src/components/ui/badge.tsx +21 -7
- package/registry/badge/files/src/lib/kit.tsx +8 -5
- package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +14 -7
- package/registry/bottom-nav/files/src/lib/kit.tsx +8 -5
- package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +7 -6
- package/registry/bottom-sheet/files/src/lib/kit.tsx +8 -5
- package/registry/button/files/src/components/ui/button.tsx +4 -3
- package/registry/button/files/src/lib/kit.tsx +8 -5
- package/registry/button-3d/files/src/components/ui/button-3d.tsx +3 -2
- package/registry/button-3d/files/src/lib/kit.tsx +8 -5
- package/registry/calendar/files/src/components/ui/calendar.tsx +9 -5
- package/registry/calendar/files/src/lib/kit.tsx +8 -5
- package/registry/card/files/src/components/ui/card.tsx +8 -6
- package/registry/card/files/src/lib/kit.tsx +8 -5
- package/registry/checkbox/files/src/components/ui/checkbox.tsx +6 -5
- package/registry/checkbox/files/src/lib/kit.tsx +8 -5
- package/registry/chip-group/files/src/components/ui/chip-group.tsx +4 -2
- package/registry/chip-group/files/src/lib/kit.tsx +8 -5
- package/registry/confetti/files/src/lib/kit.tsx +8 -5
- package/registry/coupon/files/src/components/ui/coupon.tsx +23 -20
- package/registry/coupon/files/src/components/ui/flip-card.tsx +1 -1
- package/registry/coupon/files/src/components/ui/tilt-card.tsx +2 -2
- package/registry/coupon/files/src/lib/kit.tsx +8 -5
- package/registry/date-picker/files/src/components/ui/calendar.tsx +9 -5
- package/registry/date-picker/files/src/components/ui/date-picker.tsx +2 -2
- package/registry/date-picker/files/src/lib/kit.tsx +8 -5
- package/registry/dialog/files/src/components/ui/dialog.tsx +12 -6
- package/registry/dialog/files/src/lib/kit.tsx +8 -5
- package/registry/donut-shop.json +18 -0
- package/registry/drawer/files/src/components/ui/drawer.tsx +25 -19
- package/registry/drawer/files/src/lib/kit.tsx +8 -5
- package/registry/fintech-app.json +57 -0
- package/registry/flip-card/files/src/components/ui/flip-card.tsx +1 -1
- package/registry/flip-card/files/src/lib/kit.tsx +8 -5
- package/registry/floating-input/files/src/components/ui/floating-input.tsx +16 -6
- package/registry/floating-input/files/src/lib/kit.tsx +8 -5
- package/registry/food-app.json +55 -0
- package/registry/grain/files/src/components/ui/grain.tsx +113 -0
- package/registry/{tag-input → grain}/files/src/lib/kit.tsx +8 -5
- package/registry/grain.json +17 -0
- package/registry/kit/files/src/lib/kit.tsx +8 -5
- package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +1 -1
- package/registry/liquidglass-tab/files/src/lib/tab-bar.ts +1 -1
- package/registry/list-item/files/src/components/ui/list-item.tsx +20 -16
- package/registry/list-item/files/src/lib/kit.tsx +8 -5
- package/registry/morphing-button-group.json +18 -0
- package/registry/orb-reveal.json +20 -0
- package/registry/otp-input/files/src/components/ui/otp-input.tsx +8 -6
- package/registry/otp-input/files/src/lib/kit.tsx +8 -5
- package/registry/password-input/files/src/components/ui/floating-input.tsx +16 -6
- package/registry/password-input/files/src/components/ui/password-input.tsx +2 -2
- package/registry/password-input/files/src/lib/kit.tsx +8 -5
- package/registry/payment-card/files/src/components/ui/flip-card.tsx +1 -1
- package/registry/payment-card/files/src/components/ui/payment-card.tsx +27 -14
- package/registry/payment-card/files/src/components/ui/tilt-card.tsx +2 -2
- package/registry/payment-card/files/src/lib/kit.tsx +8 -5
- package/registry/progress/files/src/components/ui/progress.tsx +8 -5
- package/registry/progress/files/src/lib/kit.tsx +8 -5
- package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +15 -11
- package/registry/progress-steps/files/src/lib/kit.tsx +8 -5
- package/registry/qr-code-button.json +18 -0
- package/registry/radio-group/files/src/components/ui/radio-group.tsx +10 -9
- package/registry/radio-group/files/src/lib/kit.tsx +8 -5
- package/registry/search-bar/files/src/components/ui/search-bar.tsx +13 -11
- package/registry/search-bar/files/src/lib/kit.tsx +8 -5
- package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +4 -2
- package/registry/segmented-control/files/src/lib/kit.tsx +8 -5
- package/registry/select/files/src/components/ui/select.tsx +3 -3
- package/registry/select/files/src/lib/kit.tsx +8 -5
- package/registry/skeleton/files/src/components/ui/skeleton.tsx +4 -4
- package/registry/skeleton/files/src/lib/kit.tsx +8 -5
- package/registry/slider/files/src/components/ui/slider.tsx +5 -4
- package/registry/slider/files/src/lib/kit.tsx +8 -5
- package/registry/spinner/files/src/components/ui/spinner.tsx +17 -12
- package/registry/spinner/files/src/lib/kit.tsx +8 -5
- package/registry/stateful-button/files/src/lib/kit.tsx +8 -5
- package/registry/stepper/files/src/components/ui/stepper.tsx +8 -4
- package/registry/stepper/files/src/lib/kit.tsx +8 -5
- package/registry/switch/files/src/components/ui/switch.tsx +4 -3
- package/registry/switch/files/src/lib/kit.tsx +8 -5
- package/registry/tabs/files/src/components/ui/tabs.tsx +10 -8
- package/registry/tabs/files/src/lib/kit.tsx +8 -5
- package/registry/text-animation/files/src/components/ui/text-animation.tsx +4 -4
- package/registry/text-animation/files/src/lib/kit.tsx +8 -5
- package/registry/textarea/files/src/components/ui/textarea.tsx +11 -9
- package/registry/textarea/files/src/lib/kit.tsx +8 -5
- package/registry/ticket-shape/files/src/lib/kit.tsx +8 -5
- package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +2 -2
- package/registry/tilt-card/files/src/lib/kit.tsx +8 -5
- package/registry/time-picker/files/src/components/ui/time-picker.tsx +2 -2
- package/registry/time-picker/files/src/lib/kit.tsx +8 -5
- package/registry/timeline/files/src/components/ui/avatar.tsx +7 -4
- package/registry/timeline/files/src/components/ui/timeline.tsx +12 -10
- package/registry/timeline/files/src/lib/kit.tsx +8 -5
- package/registry/toast/files/src/components/ui/button.tsx +4 -3
- package/registry/toast/files/src/components/ui/toast.tsx +13 -11
- package/registry/toast/files/src/lib/kit.tsx +8 -5
- package/schema/components.schema.json +1 -1
- package/registry/_docs/color-swatch.json +0 -82
- package/registry/_docs/kpi-card.json +0 -14
- package/registry/_docs/like-button.json +0 -92
- package/registry/_docs/morph-button.json +0 -128
- package/registry/_docs/pagination-dots.json +0 -108
- package/registry/_docs/shimmer-button.json +0 -98
- package/registry/_docs/tag-input.json +0 -148
- package/registry/color-swatch.json +0 -17
- package/registry/kpi-card/files/src/components/charts/kpi-card.tsx +0 -45
- package/registry/kpi-card.json +0 -14
- package/registry/like-button.json +0 -18
- package/registry/morph-button.json +0 -18
- package/registry/pagination-dots/files/src/components/ui/pagination-dots.tsx +0 -262
- package/registry/pagination-dots/files/src/lib/kit.tsx +0 -219
- package/registry/pagination-dots.json +0 -15
- package/registry/shimmer-button.json +0 -17
- package/registry/tag-input/files/src/components/ui/tag-input.tsx +0 -720
- package/registry/tag-input.json +0 -17
|
@@ -201,7 +201,8 @@ export function Calendar(props: CalendarProps) {
|
|
|
201
201
|
accent,
|
|
202
202
|
style,
|
|
203
203
|
} = props as unknown as FlatProps;
|
|
204
|
-
const { colors, radius } = useKit();
|
|
204
|
+
const { colors, radius, font } = useKit();
|
|
205
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
205
206
|
const tint = accent ?? colors.accent;
|
|
206
207
|
const fmt = useFormatters(locale);
|
|
207
208
|
|
|
@@ -368,6 +369,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
368
369
|
numberOfLines={1}
|
|
369
370
|
style={[
|
|
370
371
|
styles.title,
|
|
372
|
+
ff,
|
|
371
373
|
{ color: view === 'days' ? colors.foreground : tint },
|
|
372
374
|
view === 'days'
|
|
373
375
|
? {
|
|
@@ -390,7 +392,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
390
392
|
hitSlop={4}
|
|
391
393
|
style={({ pressed }) => [styles.todayBtn, { borderRadius: radius.capsule(32), backgroundColor: pressed ? colors.secondary : colors.muted }]}
|
|
392
394
|
>
|
|
393
|
-
<Text style={[styles.todayText, { color: tint }]}>Today</Text>
|
|
395
|
+
<Text style={[styles.todayText, ff, { color: tint }]}>Today</Text>
|
|
394
396
|
</Pressable>
|
|
395
397
|
) : null}
|
|
396
398
|
<NavButton dir={-1} disabled={prevDisabled} onPress={() => step(-1)} />
|
|
@@ -407,7 +409,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
407
409
|
>
|
|
408
410
|
<View style={styles.weekRow} accessibilityElementsHidden importantForAccessibility="no-hide-descendants">
|
|
409
411
|
{weekdays.map((w) => (
|
|
410
|
-
<Text key={w.long} numberOfLines={1} style={[styles.weekday, { color: colors.mutedForeground }]}>
|
|
412
|
+
<Text key={w.long} numberOfLines={1} style={[styles.weekday, ff, { color: colors.mutedForeground }]}>
|
|
411
413
|
{w.short}
|
|
412
414
|
</Text>
|
|
413
415
|
))}
|
|
@@ -486,7 +488,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
486
488
|
},
|
|
487
489
|
]}
|
|
488
490
|
>
|
|
489
|
-
<Text style={[styles.pickText, { color: selected ? readableOn(tint) : isNow ? tint : colors.foreground }]}>{label}</Text>
|
|
491
|
+
<Text style={[styles.pickText, ff, { color: selected ? readableOn(tint) : isNow ? tint : colors.foreground }]}>{label}</Text>
|
|
490
492
|
</View>
|
|
491
493
|
)}
|
|
492
494
|
</Pressable>
|
|
@@ -638,7 +640,8 @@ const DayCell = memo(function DayCell({
|
|
|
638
640
|
tint,
|
|
639
641
|
onPress,
|
|
640
642
|
}: DayCellProps) {
|
|
641
|
-
const { colors, radius } = useKit();
|
|
643
|
+
const { colors, radius, font } = useKit();
|
|
644
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
642
645
|
const r = tileRadius(radius.md);
|
|
643
646
|
const pop = useRef(new Animated.Value(selected ? 1 : 0)).current; // native: circle scale + opacity
|
|
644
647
|
const bandIn = useRef(new Animated.Value(band === 'none' ? 0 : 1)).current; // native: band opacity
|
|
@@ -719,6 +722,7 @@ const DayCell = memo(function DayCell({
|
|
|
719
722
|
<Text
|
|
720
723
|
style={[
|
|
721
724
|
styles.day,
|
|
725
|
+
ff,
|
|
722
726
|
{ color: textColor },
|
|
723
727
|
(today || selected) && styles.dayStrong,
|
|
724
728
|
outside && !selected && styles.outside,
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, useId, useRef, useState } from 'react';
|
|
1
|
+
import React, { createContext, useContext, useId, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Image,
|
|
@@ -98,7 +98,7 @@ export function Card({
|
|
|
98
98
|
if (highlight !== 'none') Animated.timing(glow, { toValue: 0, duration: 420, useNativeDriver: true }).start();
|
|
99
99
|
};
|
|
100
100
|
// Touch coordinates are relative to whichever child was hit, so work from page coordinates.
|
|
101
|
-
const clipRef = useRef<View
|
|
101
|
+
const clipRef = useRef<ComponentRef<typeof View>>(null);
|
|
102
102
|
const origin = useRef({ x: 0, y: 0 });
|
|
103
103
|
const placeSpot = (pageX: number, pageY: number) =>
|
|
104
104
|
spot.setValue({ x: pageX - origin.current.x - spotD / 2, y: pageY - origin.current.y - spotD / 2 });
|
|
@@ -215,18 +215,20 @@ export interface CardTextProps {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
export function CardTitle({ children, numberOfLines, style }: CardTextProps) {
|
|
218
|
-
const { colors } = useKit();
|
|
218
|
+
const { colors, font } = useKit();
|
|
219
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
219
220
|
return (
|
|
220
|
-
<Text accessibilityRole="header" numberOfLines={numberOfLines} style={[styles.title, { color: colors.cardForeground }, style]}>
|
|
221
|
+
<Text accessibilityRole="header" numberOfLines={numberOfLines} style={[styles.title, ff, { color: colors.cardForeground }, style]}>
|
|
221
222
|
{children}
|
|
222
223
|
</Text>
|
|
223
224
|
);
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
export function CardDescription({ children, numberOfLines, style }: CardTextProps) {
|
|
227
|
-
const { colors } = useKit();
|
|
228
|
+
const { colors, font } = useKit();
|
|
229
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
228
230
|
return (
|
|
229
|
-
<Text numberOfLines={numberOfLines} style={[styles.description, { color: colors.mutedForeground }, style]}>
|
|
231
|
+
<Text numberOfLines={numberOfLines} style={[styles.description, ff, { color: colors.mutedForeground }, style]}>
|
|
230
232
|
{children}
|
|
231
233
|
</Text>
|
|
232
234
|
);
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|
|
@@ -38,7 +38,8 @@ export function Checkbox({
|
|
|
38
38
|
shape = 'square',
|
|
39
39
|
style,
|
|
40
40
|
}: CheckboxProps) {
|
|
41
|
-
const { colors, radius } = useKit();
|
|
41
|
+
const { colors, radius, font } = useKit();
|
|
42
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
42
43
|
const tint = accent ?? colors.accent;
|
|
43
44
|
const corner = shape === 'circle' ? size / 2 : Math.min(size / 2, radius.sm + 1);
|
|
44
45
|
const [inner, setInner] = useState(defaultChecked);
|
|
@@ -49,7 +50,7 @@ export function Checkbox({
|
|
|
49
50
|
const burst = useRef(new Animated.Value(0)).current;
|
|
50
51
|
|
|
51
52
|
useEffect(() => {
|
|
52
|
-
Animated.spring(progress, { toValue: on ? 1 : 0, useNativeDriver: false, speed: 14, bounciness:
|
|
53
|
+
Animated.spring(progress, { toValue: on ? 1 : 0, useNativeDriver: false, speed: 14, bounciness: 0 }).start();
|
|
53
54
|
if (on) {
|
|
54
55
|
burst.setValue(0);
|
|
55
56
|
Animated.timing(burst, { toValue: 1, duration: 450, useNativeDriver: true }).start();
|
|
@@ -72,7 +73,7 @@ export function Checkbox({
|
|
|
72
73
|
disabled={disabled}
|
|
73
74
|
onPress={toggle}
|
|
74
75
|
onPressIn={() => Animated.spring(press, { toValue: 0.82, useNativeDriver: true, speed: 50 }).start()}
|
|
75
|
-
onPressOut={() => Animated.spring(press, { toValue: 1, useNativeDriver: true, speed: 20, bounciness:
|
|
76
|
+
onPressOut={() => Animated.spring(press, { toValue: 1, useNativeDriver: true, speed: 20, bounciness: 0 }).start()}
|
|
76
77
|
style={[styles.row, { opacity: disabled ? 0.5 : 1 }, style]}
|
|
77
78
|
>
|
|
78
79
|
<Animated.View style={{ transform: [{ scale: press }] }}>
|
|
@@ -119,7 +120,7 @@ export function Checkbox({
|
|
|
119
120
|
{label ? (
|
|
120
121
|
<View style={styles.text}>
|
|
121
122
|
<View style={styles.labelBox}>
|
|
122
|
-
<Animated.Text style={[styles.label, { color: progress.interpolate({ inputRange: [0, 1], outputRange: [fg, strike ? muted : fg] }) }]}>
|
|
123
|
+
<Animated.Text style={[styles.label, ff, { color: progress.interpolate({ inputRange: [0, 1], outputRange: [fg, strike ? muted : fg] }) }]}>
|
|
123
124
|
{label}
|
|
124
125
|
</Animated.Text>
|
|
125
126
|
{strike ? (
|
|
@@ -131,7 +132,7 @@ export function Checkbox({
|
|
|
131
132
|
/>
|
|
132
133
|
) : null}
|
|
133
134
|
</View>
|
|
134
|
-
{description ? <Text style={[styles.description, { color: muted }]}>{description}</Text> : null}
|
|
135
|
+
{description ? <Text style={[styles.description, ff, { color: muted }]}>{description}</Text> : null}
|
|
135
136
|
</View>
|
|
136
137
|
) : null}
|
|
137
138
|
</Pressable>
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|
|
@@ -151,7 +151,8 @@ interface ChipProps {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
function Chip({ option, active, onPress, variant, size, tint, showCheck, multiple, disabled }: ChipProps) {
|
|
154
|
-
const { colors, radius } = useKit();
|
|
154
|
+
const { colors, radius, font } = useKit();
|
|
155
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
155
156
|
// p: colours, check width + stroke (JS driver). press: squish (native, on the outer view).
|
|
156
157
|
const p = useRef(new Animated.Value(active ? 1 : 0)).current;
|
|
157
158
|
const press = useRef(new Animated.Value(1)).current;
|
|
@@ -237,7 +238,7 @@ function Chip({ option, active, onPress, variant, size, tint, showCheck, multipl
|
|
|
237
238
|
{option.label ? (
|
|
238
239
|
<Animated.Text
|
|
239
240
|
numberOfLines={1}
|
|
240
|
-
style={[styles.label, { fontSize: size.font, color: p.interpolate({ ...range, outputRange: l.fg }) }]}
|
|
241
|
+
style={[styles.label, ff, { fontSize: size.font, color: p.interpolate({ ...range, outputRange: l.fg }) }]}
|
|
241
242
|
>
|
|
242
243
|
{option.label}
|
|
243
244
|
</Animated.Text>
|
|
@@ -246,6 +247,7 @@ function Chip({ option, active, onPress, variant, size, tint, showCheck, multipl
|
|
|
246
247
|
<Animated.Text
|
|
247
248
|
style={[
|
|
248
249
|
styles.count,
|
|
250
|
+
ff,
|
|
249
251
|
{ fontSize: size.font - 1.5, color: p.interpolate({ ...range, outputRange: [colors.mutedForeground, l.fg[1]] }) },
|
|
250
252
|
]}
|
|
251
253
|
>
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|
|
@@ -198,6 +198,8 @@ function useRemaining(at?: Date | number) {
|
|
|
198
198
|
|
|
199
199
|
/** The promo code in a dashed chip; a tap copies it and flips the icon to a check for a moment. */
|
|
200
200
|
function CodeChip({ code, color, ink, fontSize, onCopy, labels }: { code: string; color: string; ink: string; fontSize: number; onCopy?: (code: string) => void; labels: Required<CouponLabels> }) {
|
|
201
|
+
const { font } = useKit();
|
|
202
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
201
203
|
const [copied, setCopied] = useState(false);
|
|
202
204
|
const [box, setBox] = useState({ w: 0, h: 0 });
|
|
203
205
|
const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
|
@@ -226,7 +228,7 @@ function CodeChip({ code, color, ink, fontSize, onCopy, labels }: { code: string
|
|
|
226
228
|
<Rect x={0.75} y={0.75} width={box.w - 1.5} height={box.h - 1.5} rx={8} fill="none" stroke={alpha(color, 0.75)} strokeWidth={1.5} strokeDasharray={[5, 4]} />
|
|
227
229
|
</Svg>
|
|
228
230
|
) : null}
|
|
229
|
-
<Text numberOfLines={1} style={{ color: ink, fontSize, fontWeight: '800', letterSpacing: 1, flexShrink: 1 }}>
|
|
231
|
+
<Text numberOfLines={1} style={[{ color: ink, fontSize, fontWeight: '800', letterSpacing: 1, flexShrink: 1 }, ff]}>
|
|
230
232
|
{code}
|
|
231
233
|
</Text>
|
|
232
234
|
{onCopy ? (
|
|
@@ -325,7 +327,8 @@ export function Coupon({
|
|
|
325
327
|
labels: labelsProp,
|
|
326
328
|
style,
|
|
327
329
|
}: CouponProps) {
|
|
328
|
-
const { colors, dark } = useKit();
|
|
330
|
+
const { colors, dark, font } = useKit();
|
|
331
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
329
332
|
const theme = typeof themeProp === 'object' ? themeProp : couponThemes[themeProp];
|
|
330
333
|
const fills = typeof theme.fill === 'string' ? [theme.fill] : theme.fill;
|
|
331
334
|
const accent = theme.accent ?? fills[fills.length - 1];
|
|
@@ -421,7 +424,7 @@ export function Coupon({
|
|
|
421
424
|
left !== undefined && left > 0 && !spent ? (
|
|
422
425
|
<View style={[styles.timer, { backgroundColor: timerBg }]}>
|
|
423
426
|
<Icon d={ICON.clock} size={11} color={timerInk} />
|
|
424
|
-
<Text style={{ color: timerInk, fontSize: 10.5, fontWeight: '800', fontVariant: ['tabular-nums'] }}>
|
|
427
|
+
<Text style={[{ color: timerInk, fontSize: 10.5, fontWeight: '800', fontVariant: ['tabular-nums'] }, ff]}>
|
|
425
428
|
{labels.endsIn} {formatCountdown(left)}
|
|
426
429
|
</Text>
|
|
427
430
|
</View>
|
|
@@ -433,7 +436,7 @@ export function Coupon({
|
|
|
433
436
|
<View style={[styles.row, { gap: 6, flexShrink: 1 }]}>
|
|
434
437
|
{logo}
|
|
435
438
|
{brand ? (
|
|
436
|
-
<Text numberOfLines={1} style={{ color: horizontal ? bodySoft : valueSoft, fontSize: 10.5, fontWeight: '800', letterSpacing: 1.2, flexShrink: 1 }}>
|
|
439
|
+
<Text numberOfLines={1} style={[{ color: horizontal ? bodySoft : valueSoft, fontSize: 10.5, fontWeight: '800', letterSpacing: 1.2, flexShrink: 1 }, ff]}>
|
|
437
440
|
{brand.toUpperCase()}
|
|
438
441
|
</Text>
|
|
439
442
|
) : null}
|
|
@@ -445,15 +448,15 @@ export function Coupon({
|
|
|
445
448
|
// Value panel ------------------------------------------------------------------------------------
|
|
446
449
|
const valueBlock = (
|
|
447
450
|
<View style={{ alignItems: 'center' }}>
|
|
448
|
-
{prefix ? <Text style={[{ color: valueSoft, fontSize: 10.5, fontWeight: '900', letterSpacing: 1.6 }, lift]}>{prefix.toUpperCase()}</Text> : null}
|
|
451
|
+
{prefix ? <Text style={[{ color: valueSoft, fontSize: 10.5, fontWeight: '900', letterSpacing: 1.6 }, ff, lift]}>{prefix.toUpperCase()}</Text> : null}
|
|
449
452
|
{locked ? <Icon d={ICON.lock} size={valueSize * 0.6} color={valueInk} /> : null}
|
|
450
453
|
{/* Vertical coupons set "50% OFF" on one line when it fits, and stack a long unit ("CASHBACK"). */}
|
|
451
454
|
<View style={{ flexDirection: inline ? 'row' : 'column', alignItems: inline ? 'flex-end' : 'center', gap: inline ? 6 : 0 }}>
|
|
452
|
-
<Text numberOfLines={1} adjustsFontSizeToFit style={[{ color: valueInk, fontSize: valueSize, lineHeight: valueSize * 1.08, fontWeight: '900', letterSpacing: -1.2 }, lift]}>
|
|
455
|
+
<Text numberOfLines={1} adjustsFontSizeToFit style={[{ color: valueInk, fontSize: valueSize, lineHeight: valueSize * 1.08, fontWeight: '900', letterSpacing: -1.2 }, ff, lift]}>
|
|
453
456
|
{value}
|
|
454
457
|
</Text>
|
|
455
458
|
{unit ? (
|
|
456
|
-
<Text style={[{ color: valueInk, fontSize: horizontal ? 12.5 : 16, fontWeight: '900', letterSpacing: 2.4, marginBottom: inline ? valueSize * 0.14 : 0 }, lift]}>
|
|
459
|
+
<Text style={[{ color: valueInk, fontSize: horizontal ? 12.5 : 16, fontWeight: '900', letterSpacing: 2.4, marginBottom: inline ? valueSize * 0.14 : 0 }, ff, lift]}>
|
|
457
460
|
{unit.toUpperCase()}
|
|
458
461
|
</Text>
|
|
459
462
|
) : null}
|
|
@@ -482,7 +485,7 @@ export function Coupon({
|
|
|
482
485
|
{brandRow}
|
|
483
486
|
{valueBlock}
|
|
484
487
|
{title ? (
|
|
485
|
-
<Text numberOfLines={2} style={[{ color: valueInk, fontSize: s.title + 1, fontWeight: '800', textAlign: 'center', letterSpacing: -0.3 }, lift]}>
|
|
488
|
+
<Text numberOfLines={2} style={[{ color: valueInk, fontSize: s.title + 1, fontWeight: '800', textAlign: 'center', letterSpacing: -0.3 }, ff, lift]}>
|
|
486
489
|
{title}
|
|
487
490
|
</Text>
|
|
488
491
|
) : null}
|
|
@@ -511,7 +514,7 @@ export function Coupon({
|
|
|
511
514
|
]}
|
|
512
515
|
>
|
|
513
516
|
{applied || locked ? <Icon d={applied ? ICON.check : ICON.lock} size={13} color={applied ? '#ffffff' : bodySoft} /> : null}
|
|
514
|
-
<Text numberOfLines={1} style={{ color: applied ? '#ffffff' : locked || spent ? bodySoft : readableOn(accent), fontSize: s.chip - 0.5, fontWeight: '800' }}>
|
|
517
|
+
<Text numberOfLines={1} style={[{ color: applied ? '#ffffff' : locked || spent ? bodySoft : readableOn(accent), fontSize: s.chip - 0.5, fontWeight: '800' }, ff]}>
|
|
515
518
|
{applied ? labels.applied : locked ? labels.locked : labels.apply}
|
|
516
519
|
</Text>
|
|
517
520
|
</Pressable>
|
|
@@ -520,11 +523,11 @@ export function Coupon({
|
|
|
520
523
|
const footer =
|
|
521
524
|
expires || canFlip ? (
|
|
522
525
|
<View style={[styles.row, { justifyContent: 'flex-start', gap: 6 }]}>
|
|
523
|
-
{expires ? <Text style={{ color: bodySoft, fontSize: 11, fontWeight: '600' }}>{expires}</Text> : null}
|
|
524
|
-
{expires && canFlip ? <Text style={{ color: bodySoft, fontSize: 11 }}>·</Text> : null}
|
|
526
|
+
{expires ? <Text style={[{ color: bodySoft, fontSize: 11, fontWeight: '600' }, ff]}>{expires}</Text> : null}
|
|
527
|
+
{expires && canFlip ? <Text style={[{ color: bodySoft, fontSize: 11 }, ff]}>·</Text> : null}
|
|
525
528
|
{canFlip ? (
|
|
526
529
|
<Pressable onPress={toggle} hitSlop={10} accessibilityRole="button" accessibilityLabel={labels.termsTitle}>
|
|
527
|
-
<Text style={{ color: textAccent, fontSize: 11, fontWeight: '800', textDecorationLine: 'underline' }}>{labels.terms}</Text>
|
|
530
|
+
<Text style={[{ color: textAccent, fontSize: 11, fontWeight: '800', textDecorationLine: 'underline' }, ff]}>{labels.terms}</Text>
|
|
528
531
|
</Pressable>
|
|
529
532
|
) : null}
|
|
530
533
|
</View>
|
|
@@ -552,16 +555,16 @@ export function Coupon({
|
|
|
552
555
|
>
|
|
553
556
|
{horizontal ? brandRow : null}
|
|
554
557
|
{horizontal && title ? (
|
|
555
|
-
<Text numberOfLines={2} style={{ color: bodyInk, fontSize: s.title, fontWeight: '800', letterSpacing: -0.3 }}>
|
|
558
|
+
<Text numberOfLines={2} style={[{ color: bodyInk, fontSize: s.title, fontWeight: '800', letterSpacing: -0.3 }, ff]}>
|
|
556
559
|
{title}
|
|
557
560
|
</Text>
|
|
558
561
|
) : null}
|
|
559
562
|
{locked && lockedHint ? (
|
|
560
|
-
<Text numberOfLines={2} style={{ color: textAccent, fontSize: s.desc, fontWeight: '700' }}>
|
|
563
|
+
<Text numberOfLines={2} style={[{ color: textAccent, fontSize: s.desc, fontWeight: '700' }, ff]}>
|
|
561
564
|
{lockedHint}
|
|
562
565
|
</Text>
|
|
563
566
|
) : description ? (
|
|
564
|
-
<Text numberOfLines={size === 'sm' ? 1 : 2} style={{ color: bodySoft, fontSize: s.desc, lineHeight: s.desc * 1.35 }}>
|
|
567
|
+
<Text numberOfLines={size === 'sm' ? 1 : 2} style={[{ color: bodySoft, fontSize: s.desc, lineHeight: s.desc * 1.35 }, ff]}>
|
|
565
568
|
{description}
|
|
566
569
|
</Text>
|
|
567
570
|
) : null}
|
|
@@ -627,23 +630,23 @@ export function Coupon({
|
|
|
627
630
|
<TicketShape {...shape} fill={body} style={StyleSheet.absoluteFill}>
|
|
628
631
|
<Pressable onPress={toggle} accessibilityRole="button" accessibilityHint={labels.back} style={[StyleSheet.absoluteFill, { padding: s.pad + edgePad, gap: 6, flexDirection: horizontal ? 'row' : 'column' }]}>
|
|
629
632
|
<View style={{ flex: 1, gap: 4 }}>
|
|
630
|
-
<Text style={{ color: bodyInk, fontSize: 12, fontWeight: '800', letterSpacing: 0.3 }}>{labels.termsTitle}</Text>
|
|
633
|
+
<Text style={[{ color: bodyInk, fontSize: 12, fontWeight: '800', letterSpacing: 0.3 }, ff]}>{labels.termsTitle}</Text>
|
|
631
634
|
{terms!.slice(0, size === 'lg' ? 5 : 4).map((t, i) => (
|
|
632
635
|
<View key={i} style={{ flexDirection: 'row', gap: 6 }}>
|
|
633
|
-
<Text style={{ color: textAccent, fontSize: 11, fontWeight: '900' }}>•</Text>
|
|
634
|
-
<Text numberOfLines={2} style={{ color: bodySoft, fontSize: 11, lineHeight: 14.5, flex: 1 }}>
|
|
636
|
+
<Text style={[{ color: textAccent, fontSize: 11, fontWeight: '900' }, ff]}>•</Text>
|
|
637
|
+
<Text numberOfLines={2} style={[{ color: bodySoft, fontSize: 11, lineHeight: 14.5, flex: 1 }, ff]}>
|
|
635
638
|
{t}
|
|
636
639
|
</Text>
|
|
637
640
|
</View>
|
|
638
641
|
))}
|
|
639
|
-
<Text style={{ color: alpha(bodyInk, 0.4), fontSize: 10, fontWeight: '700', marginTop: 'auto' }}>{labels.back}</Text>
|
|
642
|
+
<Text style={[{ color: alpha(bodyInk, 0.4), fontSize: 10, fontWeight: '700', marginTop: 'auto' }, ff]}>{labels.back}</Text>
|
|
640
643
|
</View>
|
|
641
644
|
{code ? (
|
|
642
645
|
<View style={{ alignItems: 'center', justifyContent: 'center', gap: 4 }}>
|
|
643
646
|
<View style={styles.plate}>
|
|
644
647
|
<BarcodeLike code={code} width={horizontal ? 74 : 200} height={horizontal ? 54 : 46} />
|
|
645
648
|
</View>
|
|
646
|
-
<Text style={{ color: bodyInk, fontSize: 10, fontWeight: '800', letterSpacing: 1.2 }}>{code}</Text>
|
|
649
|
+
<Text style={[{ color: bodyInk, fontSize: 10, fontWeight: '800', letterSpacing: 1.2 }, ff]}>{code}</Text>
|
|
647
650
|
</View>
|
|
648
651
|
) : null}
|
|
649
652
|
</Pressable>
|
|
@@ -121,7 +121,7 @@ export function FlipCard({
|
|
|
121
121
|
borderRadius: radius,
|
|
122
122
|
opacity,
|
|
123
123
|
transform: [{ perspective }, { [axis]: turn } as never, { scale: lift }],
|
|
124
|
-
}) as Animated.
|
|
124
|
+
}) as Animated.WithAnimatedValue<ViewStyle>;
|
|
125
125
|
|
|
126
126
|
// The shadow squeezes along the turning axis as the card goes edge-on (see SQUEEZE) and fades a little.
|
|
127
127
|
const squeeze = p.interpolate(SQUEEZE);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Easing,
|
|
@@ -267,7 +267,7 @@ export function TiltCard({
|
|
|
267
267
|
const touching = useRef(false);
|
|
268
268
|
const origin = useRef({ x: 0, y: 0 });
|
|
269
269
|
const moved = useRef(false);
|
|
270
|
-
const viewRef = useRef<View
|
|
270
|
+
const viewRef = useRef<ComponentRef<typeof View>>(null);
|
|
271
271
|
const disabledRef = useRef(disabled);
|
|
272
272
|
disabledRef.current = disabled;
|
|
273
273
|
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|
|
@@ -201,7 +201,8 @@ export function Calendar(props: CalendarProps) {
|
|
|
201
201
|
accent,
|
|
202
202
|
style,
|
|
203
203
|
} = props as unknown as FlatProps;
|
|
204
|
-
const { colors, radius } = useKit();
|
|
204
|
+
const { colors, radius, font } = useKit();
|
|
205
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
205
206
|
const tint = accent ?? colors.accent;
|
|
206
207
|
const fmt = useFormatters(locale);
|
|
207
208
|
|
|
@@ -368,6 +369,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
368
369
|
numberOfLines={1}
|
|
369
370
|
style={[
|
|
370
371
|
styles.title,
|
|
372
|
+
ff,
|
|
371
373
|
{ color: view === 'days' ? colors.foreground : tint },
|
|
372
374
|
view === 'days'
|
|
373
375
|
? {
|
|
@@ -390,7 +392,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
390
392
|
hitSlop={4}
|
|
391
393
|
style={({ pressed }) => [styles.todayBtn, { borderRadius: radius.capsule(32), backgroundColor: pressed ? colors.secondary : colors.muted }]}
|
|
392
394
|
>
|
|
393
|
-
<Text style={[styles.todayText, { color: tint }]}>Today</Text>
|
|
395
|
+
<Text style={[styles.todayText, ff, { color: tint }]}>Today</Text>
|
|
394
396
|
</Pressable>
|
|
395
397
|
) : null}
|
|
396
398
|
<NavButton dir={-1} disabled={prevDisabled} onPress={() => step(-1)} />
|
|
@@ -407,7 +409,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
407
409
|
>
|
|
408
410
|
<View style={styles.weekRow} accessibilityElementsHidden importantForAccessibility="no-hide-descendants">
|
|
409
411
|
{weekdays.map((w) => (
|
|
410
|
-
<Text key={w.long} numberOfLines={1} style={[styles.weekday, { color: colors.mutedForeground }]}>
|
|
412
|
+
<Text key={w.long} numberOfLines={1} style={[styles.weekday, ff, { color: colors.mutedForeground }]}>
|
|
411
413
|
{w.short}
|
|
412
414
|
</Text>
|
|
413
415
|
))}
|
|
@@ -486,7 +488,7 @@ export function Calendar(props: CalendarProps) {
|
|
|
486
488
|
},
|
|
487
489
|
]}
|
|
488
490
|
>
|
|
489
|
-
<Text style={[styles.pickText, { color: selected ? readableOn(tint) : isNow ? tint : colors.foreground }]}>{label}</Text>
|
|
491
|
+
<Text style={[styles.pickText, ff, { color: selected ? readableOn(tint) : isNow ? tint : colors.foreground }]}>{label}</Text>
|
|
490
492
|
</View>
|
|
491
493
|
)}
|
|
492
494
|
</Pressable>
|
|
@@ -638,7 +640,8 @@ const DayCell = memo(function DayCell({
|
|
|
638
640
|
tint,
|
|
639
641
|
onPress,
|
|
640
642
|
}: DayCellProps) {
|
|
641
|
-
const { colors, radius } = useKit();
|
|
643
|
+
const { colors, radius, font } = useKit();
|
|
644
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
642
645
|
const r = tileRadius(radius.md);
|
|
643
646
|
const pop = useRef(new Animated.Value(selected ? 1 : 0)).current; // native: circle scale + opacity
|
|
644
647
|
const bandIn = useRef(new Animated.Value(band === 'none' ? 0 : 1)).current; // native: band opacity
|
|
@@ -719,6 +722,7 @@ const DayCell = memo(function DayCell({
|
|
|
719
722
|
<Text
|
|
720
723
|
style={[
|
|
721
724
|
styles.day,
|
|
725
|
+
ff,
|
|
722
726
|
{ color: textColor },
|
|
723
727
|
(today || selected) && styles.dayStrong,
|
|
724
728
|
outside && !selected && styles.outside,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Easing,
|
|
@@ -251,7 +251,7 @@ export function DatePicker(props: DatePickerProps) {
|
|
|
251
251
|
const [draft, setDraft] = useState<Picked>(null);
|
|
252
252
|
const [calMonth, setCalMonth] = useState(new Date());
|
|
253
253
|
const [anchor, setAnchor] = useState({ x: 0, y: 0, w: 0, h: 0 });
|
|
254
|
-
const fieldRef = useRef<View
|
|
254
|
+
const fieldRef = useRef<ComponentRef<typeof View>>(null);
|
|
255
255
|
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
256
256
|
|
|
257
257
|
const ok = !error && !!success;
|
|
@@ -181,14 +181,17 @@ export function useKit(): Theme {
|
|
|
181
181
|
return useMemo(() => build(scheme, ctx?.overrides), [scheme, ctx?.overrides]);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Shared motion presets so the whole kit moves the same way. Every spring is critically damped
|
|
186
|
+
* (damping ≥ 2·√(stiffness·mass)): it settles smoothly with no overshoot or wobble.
|
|
187
|
+
*/
|
|
185
188
|
export const motion = {
|
|
186
189
|
/** Toggles, selection indicators. */
|
|
187
|
-
snappy: { damping:
|
|
188
|
-
/** Press feedback, pops. */
|
|
189
|
-
bouncy: { damping:
|
|
190
|
+
snappy: { damping: 30, stiffness: 260, mass: 0.8 },
|
|
191
|
+
/** Press feedback, pops. (Kept under its old name; it no longer bounces.) */
|
|
192
|
+
bouncy: { damping: 26, stiffness: 220, mass: 0.7 },
|
|
190
193
|
/** Sheets, layout changes. */
|
|
191
|
-
gentle: { damping:
|
|
194
|
+
gentle: { damping: 27, stiffness: 160, mass: 1 },
|
|
192
195
|
fast: 160,
|
|
193
196
|
normal: 240,
|
|
194
197
|
};
|