@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
|
@@ -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, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { createContext, useContext, useEffect, useId, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
AccessibilityInfo,
|
|
4
4
|
Animated,
|
|
@@ -131,7 +131,7 @@ interface Frame {
|
|
|
131
131
|
|
|
132
132
|
const GroupContext = createContext<{ frame: Frame | null } | null>(null);
|
|
133
133
|
|
|
134
|
-
function measure(node: View | null, e: LayoutChangeEvent, done: (f: Frame) => void) {
|
|
134
|
+
function measure(node: ComponentRef<typeof View> | null, e: LayoutChangeEvent, done: (f: Frame) => void) {
|
|
135
135
|
const { x, y, width, height } = e.nativeEvent.layout;
|
|
136
136
|
const fallback = () => done({ x, y, w: width, h: height });
|
|
137
137
|
if (!node || typeof node.measureInWindow !== 'function') return fallback();
|
|
@@ -153,7 +153,7 @@ export interface SkeletonGroupProps {
|
|
|
153
153
|
*/
|
|
154
154
|
export function SkeletonGroup({ children, style }: SkeletonGroupProps) {
|
|
155
155
|
const parent = useContext(GroupContext);
|
|
156
|
-
const ref = useRef<View
|
|
156
|
+
const ref = useRef<ComponentRef<typeof View>>(null);
|
|
157
157
|
const [frame, setFrame] = useState<Frame | null>(null);
|
|
158
158
|
const value = useMemo(() => ({ frame }), [frame]);
|
|
159
159
|
if (parent) return <View style={style}>{children}</View>;
|
|
@@ -182,7 +182,7 @@ export function Skeleton({ width = '100%', height = 14, radius = 'sm', variant =
|
|
|
182
182
|
const t = useClock(moving);
|
|
183
183
|
const group = useContext(GroupContext);
|
|
184
184
|
const win = useWindowDimensions();
|
|
185
|
-
const ref = useRef<View
|
|
185
|
+
const ref = useRef<ComponentRef<typeof View>>(null);
|
|
186
186
|
const [box, setBox] = useState<Frame | null>(null);
|
|
187
187
|
const gid = 'sk' + useId().replace(/[^a-zA-Z0-9]/g, '');
|
|
188
188
|
|
|
@@ -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
|
};
|
|
@@ -161,7 +161,8 @@ export function Slider(props: SliderProps) {
|
|
|
161
161
|
const onSlidingStart = props.onSlidingStart as Callback;
|
|
162
162
|
const onSlidingComplete = props.onSlidingComplete as Callback;
|
|
163
163
|
|
|
164
|
-
const { colors, radius, dark } = useKit();
|
|
164
|
+
const { colors, radius, dark, font } = useKit();
|
|
165
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
165
166
|
const tint = accent ?? colors.accent;
|
|
166
167
|
const onTint = accent ? readableOn(accent) : colors.accentForeground;
|
|
167
168
|
const sz = SIZES[size];
|
|
@@ -412,7 +413,7 @@ export function Slider(props: SliderProps) {
|
|
|
412
413
|
<View style={[styles.barContent, { width: w, height: trackH, paddingHorizontal: Math.round(trackH * 0.32) }]}>
|
|
413
414
|
<View>{icon !== undefined ? drawIcon(icon, iconColor) : null}</View>
|
|
414
415
|
{showValue === 'always' ? (
|
|
415
|
-
<Text numberOfLines={1} selectable={false} style={[styles.barValue, { color: textColor, fontSize: sz.font + 1 }, labelStyle]}>
|
|
416
|
+
<Text numberOfLines={1} selectable={false} style={[styles.barValue, ff, { color: textColor, fontSize: sz.font + 1 }, labelStyle]}>
|
|
416
417
|
{range ? `${fmt(vals[0])} – ${fmt(vals[1])}` : fmt(vals[0])}
|
|
417
418
|
</Text>
|
|
418
419
|
) : null}
|
|
@@ -424,7 +425,7 @@ export function Slider(props: SliderProps) {
|
|
|
424
425
|
key={key}
|
|
425
426
|
numberOfLines={1}
|
|
426
427
|
selectable={false}
|
|
427
|
-
style={[styles.markLabel, place, { fontSize: sz.font - 1, color: lit ? colors.foreground : colors.mutedForeground }, labelStyle]}
|
|
428
|
+
style={[styles.markLabel, place, ff, { fontSize: sz.font - 1, color: lit ? colors.foreground : colors.mutedForeground }, labelStyle]}
|
|
428
429
|
>
|
|
429
430
|
{text}
|
|
430
431
|
</Text>
|
|
@@ -569,7 +570,7 @@ export function Slider(props: SliderProps) {
|
|
|
569
570
|
]}
|
|
570
571
|
>
|
|
571
572
|
<View style={[styles.bubble, { backgroundColor: colors.foreground, borderRadius: radius.capsule(BUBBLE_H) }]}>
|
|
572
|
-
<Text numberOfLines={1} selectable={false} style={[styles.bubbleText, { color: colors.background, fontSize: sz.font }, labelStyle]}>
|
|
573
|
+
<Text numberOfLines={1} selectable={false} style={[styles.bubbleText, ff, { color: colors.background, fontSize: sz.font }, labelStyle]}>
|
|
573
574
|
{fmt(v)}
|
|
574
575
|
</Text>
|
|
575
576
|
</View>
|
|
@@ -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
|
};
|
|
@@ -694,25 +694,30 @@ function Ellipsis({
|
|
|
694
694
|
color: string;
|
|
695
695
|
fontSize: number;
|
|
696
696
|
}) {
|
|
697
|
+
const { font } = useKit();
|
|
698
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
697
699
|
const t = useLoop(1400 / speed, linear, true, !reduce);
|
|
698
700
|
const base = text.replace(/(…|\.{1,3})\s*$/, '');
|
|
699
701
|
return (
|
|
700
702
|
<View style={styles.ellipsis}>
|
|
701
|
-
<Text style={[styles.label, { color, fontSize }]}>{base}</Text>
|
|
703
|
+
<Text style={[styles.label, ff, { color, fontSize }]}>{base}</Text>
|
|
702
704
|
{[0, 1, 2].map((i) => (
|
|
703
705
|
<Animated.Text
|
|
704
706
|
key={i}
|
|
705
|
-
style={
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
:
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
707
|
+
style={[
|
|
708
|
+
ff,
|
|
709
|
+
{
|
|
710
|
+
color,
|
|
711
|
+
fontSize,
|
|
712
|
+
fontWeight: '400',
|
|
713
|
+
opacity: reduce
|
|
714
|
+
? 1
|
|
715
|
+
: t.interpolate({
|
|
716
|
+
inputRange: [0, 0.15 + i * 0.18, 0.3 + i * 0.18, 0.85, 1],
|
|
717
|
+
outputRange: [0, 0, 1, 1, 0],
|
|
718
|
+
}),
|
|
719
|
+
},
|
|
720
|
+
]}
|
|
716
721
|
>
|
|
717
722
|
.
|
|
718
723
|
</Animated.Text>
|
|
@@ -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
|
};
|
|
@@ -118,7 +118,8 @@ export function Stepper({
|
|
|
118
118
|
buttonStyle,
|
|
119
119
|
valueStyle,
|
|
120
120
|
}: StepperProps) {
|
|
121
|
-
const { colors, radius } = useKit();
|
|
121
|
+
const { colors, radius, font } = useKit();
|
|
122
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
122
123
|
const variant: StepperVariant = variantProp in LEGACY ? LEGACY[variantProp as StepperLegacyVariant] : (variantProp as StepperVariant);
|
|
123
124
|
const vertical = variant !== 'cart' && (orientation ? orientation === 'vertical' : variantProp === 'vertical');
|
|
124
125
|
const tint = accent ?? colors.accent;
|
|
@@ -199,6 +200,7 @@ export function Stepper({
|
|
|
199
200
|
fontSize,
|
|
200
201
|
lineHeight: Math.round(fontSize * 1.3),
|
|
201
202
|
color: numColor,
|
|
203
|
+
...ff,
|
|
202
204
|
...flatValue,
|
|
203
205
|
};
|
|
204
206
|
|
|
@@ -312,8 +314,8 @@ export function Stepper({
|
|
|
312
314
|
return (
|
|
313
315
|
<View style={[styles.labelled, style]}>
|
|
314
316
|
<View style={styles.texts}>
|
|
315
|
-
{title ? <Text style={[styles.label, { color: colors.foreground }]}>{title}</Text> : null}
|
|
316
|
-
{description ? <Text style={[styles.description, { color: colors.mutedForeground }]}>{description}</Text> : null}
|
|
317
|
+
{title ? <Text style={[styles.label, ff, { color: colors.foreground }]}>{title}</Text> : null}
|
|
318
|
+
{description ? <Text style={[styles.description, ff, { color: colors.mutedForeground }]}>{description}</Text> : null}
|
|
317
319
|
</View>
|
|
318
320
|
{control}
|
|
319
321
|
</View>
|
|
@@ -361,6 +363,8 @@ function CartControl({
|
|
|
361
363
|
onAdd: () => void;
|
|
362
364
|
onAddEnd: () => void;
|
|
363
365
|
} & React.ComponentProps<typeof View>) {
|
|
366
|
+
const { font } = useKit();
|
|
367
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
364
368
|
// Natural widths, measured off-screen so the spring always lands on the real size.
|
|
365
369
|
const [textW, setTextW] = useState(0);
|
|
366
370
|
const [addW, setAddW] = useState(0);
|
|
@@ -438,7 +442,7 @@ function CartControl({
|
|
|
438
442
|
style={({ pressed }) => [styles.add, { height: s.btn, paddingHorizontal: Math.round(s.btn * 0.36) }, pressed && { backgroundColor: alpha(fg, 0.16) }]}
|
|
439
443
|
>
|
|
440
444
|
<Glyph d={ICON.plus} size={s.icon} color={fg} />
|
|
441
|
-
<Text style={[styles.addText, { color: fg, fontSize: s.font - 2 }]}>{addLabel}</Text>
|
|
445
|
+
<Text style={[styles.addText, ff, { color: fg, fontSize: s.font - 2 }]}>{addLabel}</Text>
|
|
442
446
|
</Pressable>
|
|
443
447
|
</Animated.View>
|
|
444
448
|
</View>
|
|
@@ -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
|
};
|
|
@@ -63,7 +63,8 @@ export function Switch({
|
|
|
63
63
|
accessibilityLabel,
|
|
64
64
|
style,
|
|
65
65
|
}: SwitchProps) {
|
|
66
|
-
const { colors, dark } = useKit();
|
|
66
|
+
const { colors, dark, font } = useKit();
|
|
67
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
67
68
|
const gid = 'sw' + useId().replace(/[^a-zA-Z0-9]/g, '');
|
|
68
69
|
const tint = accent ?? colors.accent;
|
|
69
70
|
const [inner, setInner] = useState(defaultValue);
|
|
@@ -315,8 +316,8 @@ export function Switch({
|
|
|
315
316
|
return (
|
|
316
317
|
<Pressable {...a11y} style={[styles.row, { opacity: disabled ? 0.45 : 1 }, style]}>
|
|
317
318
|
<View style={styles.text}>
|
|
318
|
-
<Text style={[styles.label, { color: colors.foreground }]}>{label}</Text>
|
|
319
|
-
{description ? <Text style={[styles.description, { color: colors.mutedForeground }]}>{description}</Text> : null}
|
|
319
|
+
<Text style={[styles.label, ff, { color: colors.foreground }]}>{label}</Text>
|
|
320
|
+
{description ? <Text style={[styles.description, ff, { color: colors.mutedForeground }]}>{description}</Text> : null}
|
|
320
321
|
</View>
|
|
321
322
|
{control}
|
|
322
323
|
</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
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Haptics from 'expo-haptics';
|
|
2
|
-
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import React, { useEffect, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
3
3
|
import {
|
|
4
4
|
AccessibilityInfo,
|
|
5
5
|
Animated,
|
|
@@ -64,7 +64,7 @@ type Box = { x: number; w: number };
|
|
|
64
64
|
|
|
65
65
|
// Liquid move: the edge in the direction of travel leads, the other one trails behind.
|
|
66
66
|
const LEAD = motion.snappy;
|
|
67
|
-
const TRAIL = { damping:
|
|
67
|
+
const TRAIL = { damping: 24, stiffness: 150, mass: 0.9 };
|
|
68
68
|
const UNDERLINE = 3;
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -123,7 +123,7 @@ export function Tabs({
|
|
|
123
123
|
const release = useRef({ v: 0, dragged: false });
|
|
124
124
|
const paging = useRef(false); // pager spring in flight (its JS value is stale until it ends)
|
|
125
125
|
const [settle, setSettle] = useState(0);
|
|
126
|
-
const scrollRef = useRef<ScrollView
|
|
126
|
+
const scrollRef = useRef<ComponentRef<typeof ScrollView>>(null);
|
|
127
127
|
|
|
128
128
|
const edgesOf = (i: number): [number, number] | null => {
|
|
129
129
|
const t = tabs.current[i];
|
|
@@ -173,7 +173,7 @@ export function Tabs({
|
|
|
173
173
|
Animated.timing(pan, { toValue: to, duration: 180, useNativeDriver: true }).start();
|
|
174
174
|
} else {
|
|
175
175
|
paging.current = true;
|
|
176
|
-
Animated.spring(pan, { toValue: to, velocity: v, useNativeDriver: true, ...motion.snappy, damping:
|
|
176
|
+
Animated.spring(pan, { toValue: to, velocity: v, useNativeDriver: true, ...motion.snappy, damping: 30 }).start(
|
|
177
177
|
({ finished }) => {
|
|
178
178
|
if (finished) paging.current = false;
|
|
179
179
|
}
|
|
@@ -425,7 +425,8 @@ interface TabProps {
|
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
function Tab({ item, active, mode, height, fontSize, tint, reduce, onPress, onLayout, onLabelLayout }: TabProps) {
|
|
428
|
-
const { colors } = useKit();
|
|
428
|
+
const { colors, font } = useKit();
|
|
429
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
429
430
|
const a = useRef(new Animated.Value(active ? 1 : 0)).current; // label colour (JS)
|
|
430
431
|
const press = useRef(new Animated.Value(1)).current; // squish (native)
|
|
431
432
|
|
|
@@ -462,7 +463,7 @@ function Tab({ item, active, mode, height, fontSize, tint, reduce, onPress, onLa
|
|
|
462
463
|
{/* Measured: the underline spans exactly this (icon + label). */}
|
|
463
464
|
<Animated.View onLayout={onLabelLayout} style={[styles.labelRow, { transform: [{ scale: press }] }]}>
|
|
464
465
|
{icon}
|
|
465
|
-
<Animated.Text numberOfLines={1} style={[styles.label, { color, fontSize }]}>
|
|
466
|
+
<Animated.Text numberOfLines={1} style={[styles.label, ff, { color, fontSize }]}>
|
|
466
467
|
{item.label}
|
|
467
468
|
</Animated.Text>
|
|
468
469
|
</Animated.View>
|
|
@@ -473,7 +474,8 @@ function Tab({ item, active, mode, height, fontSize, tint, reduce, onPress, onLa
|
|
|
473
474
|
|
|
474
475
|
/** Count bubble: accent when its tab is active, muted otherwise. Pops when the value changes. */
|
|
475
476
|
function TabBadge({ value, active, tint, reduce }: { value: number | string; active: boolean; tint: string; reduce: boolean }) {
|
|
476
|
-
const { colors, radius, dark } = useKit();
|
|
477
|
+
const { colors, radius, dark, font } = useKit();
|
|
478
|
+
const ff = font.family ? { fontFamily: font.family } : null;
|
|
477
479
|
const s = useRef(new Animated.Value(1)).current;
|
|
478
480
|
const first = useRef(true);
|
|
479
481
|
useEffect(() => {
|
|
@@ -496,7 +498,7 @@ function TabBadge({ value, active, tint, reduce }: { value: number | string; act
|
|
|
496
498
|
},
|
|
497
499
|
]}
|
|
498
500
|
>
|
|
499
|
-
<Animated.Text style={[styles.badgeText, { color: active ? readableOn(tint) : colors.mutedForeground }]}>{text}</Animated.Text>
|
|
501
|
+
<Animated.Text style={[styles.badgeText, ff, { color: active ? readableOn(tint) : colors.mutedForeground }]}>{text}</Animated.Text>
|
|
500
502
|
</Animated.View>
|
|
501
503
|
);
|
|
502
504
|
}
|
|
@@ -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
|
};
|
|
@@ -114,10 +114,10 @@ function nextStop(text: string, from: number) {
|
|
|
114
114
|
|
|
115
115
|
const easeOut = (t: number) => 1 - Math.pow(1 - t, 3);
|
|
116
116
|
const easeInOut = (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2);
|
|
117
|
-
/** A soft
|
|
118
|
-
const soft = (t: number) => 1 - Math.exp(-
|
|
119
|
-
/** A firmer settle
|
|
120
|
-
const settle = (t: number) => 1 - Math.exp(-
|
|
117
|
+
/** A soft, critically damped settle (no overshoot), sampled as a curve so it runs on the native driver. */
|
|
118
|
+
const soft = (t: number) => 1 - Math.exp(-7 * t) * (1 + 7 * t);
|
|
119
|
+
/** A firmer settle, also without overshoot. */
|
|
120
|
+
const settle = (t: number) => 1 - Math.exp(-8 * t) * (1 + 8 * t);
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* Maps a millisecond clock onto `from → to` between `start` and `start + dur` through `ease`.
|
|
@@ -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, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
1
|
+
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Easing,
|
|
@@ -97,7 +97,7 @@ const AnimatedCircle = Animated.createAnimatedComponent(Circle);
|
|
|
97
97
|
* optional floating label, a focus halo, a counter that morphs into a progress ring near
|
|
98
98
|
* `maxLength`, and a `toolbar` slot for chat composers.
|
|
99
99
|
*/
|
|
100
|
-
export const Textarea = forwardRef<TextInput
|
|
100
|
+
export const Textarea = forwardRef<ComponentRef<typeof TextInput>, TextareaProps>(function Textarea(
|
|
101
101
|
{
|
|
102
102
|
label,
|
|
103
103
|
floatingLabel = true,
|
|
@@ -143,16 +143,18 @@ export const Textarea = forwardRef<TextInput, TextareaProps>(function Textarea(
|
|
|
143
143
|
const LINE = typeof userInput.lineHeight === 'number' ? userInput.lineHeight : Math.round((FONT * S.line) / S.font);
|
|
144
144
|
const corner = typeof userField.borderRadius === 'number' ? userField.borderRadius : radius.md;
|
|
145
145
|
// The hidden mirror must measure text exactly like the input does.
|
|
146
|
-
const metrics: TextStyle = {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
const metrics: TextStyle = {
|
|
147
|
+
...ff,
|
|
148
|
+
...(userInput.fontFamily !== undefined ? { fontFamily: userInput.fontFamily } : null),
|
|
149
|
+
...(userInput.fontWeight !== undefined ? { fontWeight: userInput.fontWeight } : null),
|
|
150
|
+
...(userInput.fontStyle !== undefined ? { fontStyle: userInput.fontStyle } : null),
|
|
151
|
+
...(userInput.letterSpacing !== undefined ? { letterSpacing: userInput.letterSpacing } : null),
|
|
152
|
+
};
|
|
151
153
|
const tint = accent ?? colors.accent;
|
|
152
154
|
const bg = surface ?? colors.background;
|
|
153
155
|
const filled = variant === 'filled';
|
|
154
|
-
const inputRef = useRef<TextInput
|
|
155
|
-
useImperativeHandle(ref, () => inputRef.current as TextInput);
|
|
156
|
+
const inputRef = useRef<ComponentRef<typeof TextInput>>(null);
|
|
157
|
+
useImperativeHandle(ref, () => inputRef.current as ComponentRef<typeof TextInput>);
|
|
156
158
|
|
|
157
159
|
const [focused, setFocused] = useState(false);
|
|
158
160
|
const [inner, setInner] = useState(defaultValue ?? '');
|
|
@@ -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
|
};
|
|
@@ -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
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo, useEffect, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { memo, useEffect, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Easing,
|
|
@@ -255,7 +255,7 @@ const WheelColumn = memo(function WheelColumn({ items, index, onIndexChange, lab
|
|
|
255
255
|
const { colors, font } = useKit();
|
|
256
256
|
const ff = font.family ? { fontFamily: font.family } : null;
|
|
257
257
|
const scrollY = useRef(new Animated.Value(index * ITEM)).current; // native, driven by the scroll view
|
|
258
|
-
const ref = useRef<ScrollView
|
|
258
|
+
const ref = useRef<ComponentRef<typeof ScrollView>>(null);
|
|
259
259
|
const settled = useRef(index);
|
|
260
260
|
const dragging = useRef(false);
|
|
261
261
|
const lastY = useRef(index * ITEM);
|