@retray-dev/ui-kit 6.1.0 → 6.2.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/COMPONENTS.md +4 -4
- package/dist/index.d.mts +42 -21
- package/dist/index.d.ts +42 -21
- package/dist/index.js +679 -628
- package/dist/index.mjs +672 -621
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +10 -12
- package/src/components/Button/Button.tsx +20 -18
- package/src/components/Card/Card.tsx +21 -33
- package/src/components/CategoryStrip/CategoryStrip.tsx +45 -38
- package/src/components/Checkbox/Checkbox.tsx +31 -50
- package/src/components/Chip/Chip.tsx +34 -71
- package/src/components/IconButton/IconButton.tsx +20 -18
- package/src/components/Input/Input.tsx +39 -22
- package/src/components/ListItem/ListItem.tsx +22 -34
- package/src/components/MediaCard/MediaCard.tsx +24 -24
- package/src/components/MenuItem/MenuItem.tsx +22 -31
- package/src/components/MonthPicker/MonthPicker.tsx +12 -2
- package/src/components/Pressable/Pressable.tsx +27 -46
- package/src/components/Progress/Progress.tsx +21 -12
- package/src/components/RadioGroup/RadioGroup.tsx +52 -26
- package/src/components/Select/Select.tsx +17 -15
- package/src/components/Sheet/Sheet.tsx +4 -1
- package/src/components/Skeleton/Skeleton.tsx +24 -13
- package/src/components/Slider/Slider.tsx +11 -1
- package/src/components/Switch/Switch.tsx +44 -49
- package/src/components/Tabs/Tabs.tsx +39 -31
- package/src/components/Textarea/Textarea.tsx +29 -12
- package/src/components/Toggle/Toggle.tsx +39 -45
- package/src/utils/animations.ts +58 -0
- package/src/utils/useColorTransition.ts +40 -0
- package/src/utils/usePressScale.ts +73 -0
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import React26, { createContext, useMemo, useContext,
|
|
2
|
-
import { Platform, StyleSheet, Dimensions, useColorScheme,
|
|
1
|
+
import React26, { createContext, useMemo, useContext, useState, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { Platform, StyleSheet, Dimensions, useColorScheme, TouchableOpacity, ActivityIndicator, Text, View, TextInput, Image, Modal, ScrollView, Pressable } from 'react-native';
|
|
3
|
+
import Animated9, { Easing, useAnimatedStyle, interpolateColor, useSharedValue, withRepeat, withTiming, withSpring, useDerivedValue } from 'react-native-reanimated';
|
|
3
4
|
import { verticalScale, scale, moderateVerticalScale, moderateScale } from 'react-native-size-matters';
|
|
4
5
|
import AntDesign from '@expo/vector-icons/AntDesign';
|
|
5
6
|
import Entypo from '@expo/vector-icons/Entypo';
|
|
@@ -9,7 +10,6 @@ import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
|
|
9
10
|
import Ionicons from '@expo/vector-icons/Ionicons';
|
|
10
11
|
import { AntDesign as AntDesign$1, FontAwesome5 as FontAwesome5$1, MaterialIcons as MaterialIcons$1, Entypo as Entypo$1, Feather as Feather$1 } from '@expo/vector-icons';
|
|
11
12
|
import { LinearGradient } from 'expo-linear-gradient';
|
|
12
|
-
import Animated12, { Easing, useSharedValue, useDerivedValue, withTiming, useAnimatedStyle } from 'react-native-reanimated';
|
|
13
13
|
import RNSlider from '@react-native-community/slider';
|
|
14
14
|
import { BottomSheetBackdrop, BottomSheetFooter, BottomSheetModal, BottomSheetScrollView, BottomSheetView } from '@gorhom/bottom-sheet';
|
|
15
15
|
export { BottomSheetModalProvider, BottomSheetTextInput as SheetTextInput } from '@gorhom/bottom-sheet';
|
|
@@ -407,9 +407,87 @@ var TYPOGRAPHY = {
|
|
|
407
407
|
letterSpacing: 0
|
|
408
408
|
}
|
|
409
409
|
};
|
|
410
|
+
var SPRINGS = {
|
|
411
|
+
/** Tight, premium press feel — Buttons, Toggle, Tabs triggers. */
|
|
412
|
+
pressIn: { stiffness: 600, damping: 35, mass: 0.8 },
|
|
413
|
+
pressOut: { stiffness: 280, damping: 22, mass: 0.8 },
|
|
414
|
+
/** Slightly softer for larger surfaces — Card, ListItem, MenuItem. */
|
|
415
|
+
surfacePressIn: { stiffness: 380, damping: 30, mass: 0.95 },
|
|
416
|
+
surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 },
|
|
417
|
+
/** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
|
|
418
|
+
glide: { stiffness: 380, damping: 38, mass: 1 },
|
|
419
|
+
/** Elastic indicator — Switch thumb, RadioGroup dot. */
|
|
420
|
+
elastic: { stiffness: 320, damping: 22, mass: 0.7 }
|
|
421
|
+
};
|
|
422
|
+
var TIMINGS = {
|
|
423
|
+
/** Color/opacity transitions on toggles, checkboxes, switches. */
|
|
424
|
+
state: { duration: 160 },
|
|
425
|
+
/** Focus ring on inputs. */
|
|
426
|
+
focusIn: { duration: 140 },
|
|
427
|
+
focusOut: { duration: 100 },
|
|
428
|
+
/** Accordion / collapsible content. */
|
|
429
|
+
expand: { duration: 240 },
|
|
430
|
+
collapse: { duration: 200 },
|
|
431
|
+
/** Skeleton shimmer cycle (full pass). */
|
|
432
|
+
shimmer: { duration: 1400 }
|
|
433
|
+
};
|
|
434
|
+
var EASINGS = {
|
|
435
|
+
/** Material-style ease-out — natural deceleration for state changes. */
|
|
436
|
+
standard: Easing.bezier(0.2, 0, 0, 1),
|
|
437
|
+
/** Strong ease-out for expanding surfaces (Accordion open). */
|
|
438
|
+
expand: Easing.bezier(0.23, 1, 0.32, 1),
|
|
439
|
+
/** Quick ease-in for collapsing. */
|
|
440
|
+
collapse: Easing.in(Easing.ease)
|
|
441
|
+
};
|
|
442
|
+
var PRESS_SCALE = {
|
|
443
|
+
button: 0.95,
|
|
444
|
+
card: 0.98,
|
|
445
|
+
row: 0.97,
|
|
446
|
+
chip: 0.94
|
|
447
|
+
};
|
|
448
|
+
function useHover() {
|
|
449
|
+
const [hovered, setHovered] = useState(false);
|
|
450
|
+
const onMouseEnter = useCallback(() => setHovered(true), []);
|
|
451
|
+
const onMouseLeave = useCallback(() => setHovered(false), []);
|
|
452
|
+
if (Platform.OS !== "web") {
|
|
453
|
+
return { hovered: false, hoverHandlers: {} };
|
|
454
|
+
}
|
|
455
|
+
return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/utils/usePressScale.ts
|
|
459
|
+
function usePressScale({
|
|
460
|
+
pressScale = PRESS_SCALE.button,
|
|
461
|
+
hoverScale = 1.02,
|
|
462
|
+
pressInSpring = SPRINGS.pressIn,
|
|
463
|
+
pressOutSpring = SPRINGS.pressOut,
|
|
464
|
+
disabled = false
|
|
465
|
+
} = {}) {
|
|
466
|
+
const scale2 = useSharedValue(1);
|
|
467
|
+
const { hovered, hoverHandlers } = useHover();
|
|
468
|
+
const onPressIn = useCallback(() => {
|
|
469
|
+
if (disabled) return;
|
|
470
|
+
scale2.value = withSpring(pressScale, pressInSpring);
|
|
471
|
+
}, [disabled, pressScale, pressInSpring, scale2]);
|
|
472
|
+
const onPressOut = useCallback(() => {
|
|
473
|
+
if (disabled) return;
|
|
474
|
+
scale2.value = withSpring(1, pressOutSpring);
|
|
475
|
+
}, [disabled, pressOutSpring, scale2]);
|
|
476
|
+
const hoverActive = Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
|
|
477
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
478
|
+
transform: [
|
|
479
|
+
{ scale: scale2.value * (hoverActive ? hoverScale : 1) }
|
|
480
|
+
]
|
|
481
|
+
}));
|
|
482
|
+
return {
|
|
483
|
+
animatedStyle,
|
|
484
|
+
onPressIn,
|
|
485
|
+
onPressOut,
|
|
486
|
+
hoverHandlers
|
|
487
|
+
};
|
|
488
|
+
}
|
|
410
489
|
|
|
411
490
|
// src/components/Button/Button.tsx
|
|
412
|
-
var nativeDriver = Platform.OS !== "web";
|
|
413
491
|
var containerSizeStyles = {
|
|
414
492
|
sm: { paddingHorizontal: s(16), paddingVertical: vs(10), minHeight: 40 },
|
|
415
493
|
md: { paddingHorizontal: s(24), paddingVertical: vs(14), minHeight: 48 },
|
|
@@ -434,18 +512,16 @@ function Button({
|
|
|
434
512
|
disabled,
|
|
435
513
|
style,
|
|
436
514
|
onPress,
|
|
515
|
+
accessibilityLabel,
|
|
516
|
+
accessibilityHint,
|
|
437
517
|
...props
|
|
438
518
|
}) {
|
|
439
519
|
const { colors } = useTheme();
|
|
440
520
|
const isDisabled = disabled || loading;
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
};
|
|
446
|
-
const handlePressOut = () => {
|
|
447
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver, stiffness: 280, damping: 22, mass: 0.8 }).start();
|
|
448
|
-
};
|
|
521
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
522
|
+
pressScale: PRESS_SCALE.button,
|
|
523
|
+
disabled: isDisabled
|
|
524
|
+
});
|
|
449
525
|
const handlePress = (e) => {
|
|
450
526
|
impactMedium();
|
|
451
527
|
onPress?.(e);
|
|
@@ -468,43 +544,54 @@ function Button({
|
|
|
468
544
|
const styleArray = Array.isArray(style) ? style : style ? [style] : [];
|
|
469
545
|
const flatStyle = StyleSheet.flatten(styleArray);
|
|
470
546
|
const { flex, ...restStyle } = flatStyle || {};
|
|
471
|
-
return /* @__PURE__ */ React26.createElement(
|
|
472
|
-
|
|
547
|
+
return /* @__PURE__ */ React26.createElement(
|
|
548
|
+
Animated9.View,
|
|
473
549
|
{
|
|
474
|
-
style: [
|
|
475
|
-
|
|
476
|
-
containerVariantStyle,
|
|
477
|
-
containerSizeStyles[size],
|
|
478
|
-
fullWidth && styles.fullWidth,
|
|
479
|
-
isDisabled && styles.disabled,
|
|
480
|
-
restStyle
|
|
481
|
-
],
|
|
482
|
-
disabled: isDisabled,
|
|
483
|
-
activeOpacity: 1,
|
|
484
|
-
touchSoundDisabled: true,
|
|
485
|
-
onPress: handlePress,
|
|
486
|
-
onPressIn: handlePressIn,
|
|
487
|
-
onPressOut: handlePressOut,
|
|
488
|
-
...props
|
|
550
|
+
style: [fullWidth && styles.fullWidth, flex !== void 0 && { flex }, animatedStyle],
|
|
551
|
+
...hoverHandlers
|
|
489
552
|
},
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
{
|
|
493
|
-
style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
|
|
494
|
-
allowFontScaling: true,
|
|
495
|
-
numberOfLines: 1
|
|
496
|
-
},
|
|
497
|
-
label
|
|
498
|
-
)) : /* @__PURE__ */ React26.createElement(React26.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, effectiveIcon), /* @__PURE__ */ React26.createElement(
|
|
499
|
-
Text,
|
|
553
|
+
/* @__PURE__ */ React26.createElement(
|
|
554
|
+
TouchableOpacity,
|
|
500
555
|
{
|
|
501
|
-
style: [
|
|
502
|
-
|
|
503
|
-
|
|
556
|
+
style: [
|
|
557
|
+
styles.base,
|
|
558
|
+
containerVariantStyle,
|
|
559
|
+
containerSizeStyles[size],
|
|
560
|
+
fullWidth && styles.fullWidth,
|
|
561
|
+
isDisabled && styles.disabled,
|
|
562
|
+
restStyle
|
|
563
|
+
],
|
|
564
|
+
disabled: isDisabled,
|
|
565
|
+
activeOpacity: 1,
|
|
566
|
+
touchSoundDisabled: true,
|
|
567
|
+
onPress: handlePress,
|
|
568
|
+
onPressIn,
|
|
569
|
+
onPressOut,
|
|
570
|
+
accessibilityRole: "button",
|
|
571
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
572
|
+
accessibilityHint,
|
|
573
|
+
accessibilityState: { disabled: isDisabled, busy: loading },
|
|
574
|
+
...props
|
|
504
575
|
},
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
576
|
+
loading ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React26.createElement(
|
|
577
|
+
Text,
|
|
578
|
+
{
|
|
579
|
+
style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
|
|
580
|
+
allowFontScaling: true,
|
|
581
|
+
numberOfLines: 1
|
|
582
|
+
},
|
|
583
|
+
label
|
|
584
|
+
)) : /* @__PURE__ */ React26.createElement(React26.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, effectiveIcon), /* @__PURE__ */ React26.createElement(
|
|
585
|
+
Text,
|
|
586
|
+
{
|
|
587
|
+
style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
|
|
588
|
+
allowFontScaling: true,
|
|
589
|
+
numberOfLines: 1
|
|
590
|
+
},
|
|
591
|
+
label
|
|
592
|
+
), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, effectiveIcon))
|
|
593
|
+
)
|
|
594
|
+
);
|
|
508
595
|
}
|
|
509
596
|
var styles = StyleSheet.create({
|
|
510
597
|
base: {
|
|
@@ -564,7 +651,6 @@ var styles2 = StyleSheet.create({
|
|
|
564
651
|
flexDirection: "column"
|
|
565
652
|
}
|
|
566
653
|
});
|
|
567
|
-
var nativeDriver2 = Platform.OS !== "web";
|
|
568
654
|
var sizeMap = {
|
|
569
655
|
sm: { container: s(32), icon: 16 },
|
|
570
656
|
md: { container: s(44), icon: 20 },
|
|
@@ -581,18 +667,16 @@ function IconButton({
|
|
|
581
667
|
disabled,
|
|
582
668
|
style,
|
|
583
669
|
onPress,
|
|
670
|
+
accessibilityLabel,
|
|
671
|
+
accessibilityHint,
|
|
584
672
|
...props
|
|
585
673
|
}) {
|
|
586
674
|
const { colors } = useTheme();
|
|
587
675
|
const isDisabled = disabled || loading;
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
};
|
|
593
|
-
const handlePressOut = () => {
|
|
594
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver2, speed: 40, bounciness: 4 }).start();
|
|
595
|
-
};
|
|
676
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
677
|
+
pressScale: PRESS_SCALE.button,
|
|
678
|
+
disabled: isDisabled
|
|
679
|
+
});
|
|
596
680
|
const handlePress = (e) => {
|
|
597
681
|
impactLight();
|
|
598
682
|
onPress?.(e);
|
|
@@ -617,30 +701,42 @@ function IconButton({
|
|
|
617
701
|
const showBadge = badge !== void 0 && badge !== false && badge !== 0;
|
|
618
702
|
const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
|
|
619
703
|
const showCount = typeof badge === "number" && badge > 0;
|
|
620
|
-
return /* @__PURE__ */ React26.createElement(
|
|
621
|
-
|
|
704
|
+
return /* @__PURE__ */ React26.createElement(
|
|
705
|
+
Animated9.View,
|
|
622
706
|
{
|
|
623
|
-
style: [
|
|
624
|
-
|
|
625
|
-
containerVariantStyle,
|
|
626
|
-
{ width: containerSize, height: containerSize },
|
|
627
|
-
isDisabled && styles3.disabled,
|
|
628
|
-
style
|
|
629
|
-
],
|
|
630
|
-
disabled: isDisabled,
|
|
631
|
-
activeOpacity: 1,
|
|
632
|
-
touchSoundDisabled: true,
|
|
633
|
-
onPress: handlePress,
|
|
634
|
-
onPressIn: handlePressIn,
|
|
635
|
-
onPressOut: handlePressOut,
|
|
636
|
-
...props
|
|
707
|
+
style: [styles3.wrapper, animatedStyle],
|
|
708
|
+
...hoverHandlers
|
|
637
709
|
},
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
710
|
+
/* @__PURE__ */ React26.createElement(
|
|
711
|
+
TouchableOpacity,
|
|
712
|
+
{
|
|
713
|
+
style: [
|
|
714
|
+
styles3.base,
|
|
715
|
+
containerVariantStyle,
|
|
716
|
+
{ width: containerSize, height: containerSize },
|
|
717
|
+
isDisabled && styles3.disabled,
|
|
718
|
+
style
|
|
719
|
+
],
|
|
720
|
+
disabled: isDisabled,
|
|
721
|
+
activeOpacity: 1,
|
|
722
|
+
touchSoundDisabled: true,
|
|
723
|
+
onPress: handlePress,
|
|
724
|
+
onPressIn,
|
|
725
|
+
onPressOut,
|
|
726
|
+
accessibilityRole: "button",
|
|
727
|
+
accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
|
|
728
|
+
accessibilityHint,
|
|
729
|
+
accessibilityState: { disabled: isDisabled, busy: loading },
|
|
730
|
+
...props
|
|
731
|
+
},
|
|
732
|
+
loading ? /* @__PURE__ */ React26.createElement(ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
|
|
733
|
+
),
|
|
734
|
+
showBadge && /* @__PURE__ */ React26.createElement(View, { style: [
|
|
735
|
+
styles3.badge,
|
|
736
|
+
{ backgroundColor: colors.primary },
|
|
737
|
+
showCount ? styles3.badgeCount : styles3.badgeDot
|
|
738
|
+
] }, showCount && /* @__PURE__ */ React26.createElement(Text, { style: [styles3.badgeText, { color: colors.primaryForeground }] }, badgeCount))
|
|
739
|
+
);
|
|
644
740
|
}
|
|
645
741
|
var styles3 = StyleSheet.create({
|
|
646
742
|
wrapper: {
|
|
@@ -729,29 +825,49 @@ function Text3({ variant = "body-md", color, style, children, ...props }) {
|
|
|
729
825
|
children
|
|
730
826
|
);
|
|
731
827
|
}
|
|
828
|
+
function useColorTransition(active, options = {}) {
|
|
829
|
+
const { duration = TIMINGS.state.duration } = options;
|
|
830
|
+
const progress = useSharedValue(active ? 1 : 0);
|
|
831
|
+
useEffect(() => {
|
|
832
|
+
progress.value = withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard });
|
|
833
|
+
}, [active, duration, progress]);
|
|
834
|
+
return progress;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// src/components/Input/Input.tsx
|
|
732
838
|
var webInputResetStyle = Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
|
|
733
|
-
function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, ...props }) {
|
|
839
|
+
function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
|
|
734
840
|
const { colors } = useTheme();
|
|
735
841
|
const [focused, setFocused] = useState(false);
|
|
736
842
|
const [showPassword, setShowPassword] = useState(false);
|
|
737
|
-
const
|
|
843
|
+
const focusProgress = useColorTransition(focused, {
|
|
844
|
+
duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
|
|
845
|
+
});
|
|
738
846
|
const isDisabled = disabled || editable === false;
|
|
739
847
|
const isPassword = type === "password";
|
|
740
848
|
const effectiveSecure = isPassword ? !showPassword : secureTextEntry;
|
|
741
849
|
const effectivePrefix = prefixIcon ? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.foregroundMuted) : prefix;
|
|
742
|
-
const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React26.createElement(
|
|
850
|
+
const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React26.createElement(
|
|
851
|
+
TouchableOpacity,
|
|
852
|
+
{
|
|
853
|
+
onPress: () => setShowPassword(!showPassword),
|
|
854
|
+
style: styles4.passwordToggle,
|
|
855
|
+
activeOpacity: 0.6,
|
|
856
|
+
accessibilityRole: "button",
|
|
857
|
+
accessibilityLabel: showPassword ? "Hide password" : "Show password"
|
|
858
|
+
},
|
|
859
|
+
/* @__PURE__ */ React26.createElement(AntDesign$1, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.foregroundMuted })
|
|
860
|
+
) : suffixIcon ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted) : suffix;
|
|
861
|
+
const borderColorStyle = useAnimatedStyle(() => ({
|
|
862
|
+
borderColor: error ? colors.destructive : interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary])
|
|
863
|
+
}));
|
|
743
864
|
return /* @__PURE__ */ React26.createElement(View, { style: [styles4.container, isDisabled && styles4.containerDisabled, containerStyle] }, label ? /* @__PURE__ */ React26.createElement(Text, { style: [styles4.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React26.createElement(
|
|
744
|
-
|
|
865
|
+
Animated9.View,
|
|
745
866
|
{
|
|
746
867
|
style: [
|
|
747
868
|
styles4.inputWrapper,
|
|
748
|
-
{
|
|
749
|
-
|
|
750
|
-
inputRange: [0, 1],
|
|
751
|
-
outputRange: [colors.border, colors.primary]
|
|
752
|
-
}),
|
|
753
|
-
backgroundColor: isDisabled ? colors.surface : colors.background
|
|
754
|
-
},
|
|
869
|
+
{ backgroundColor: isDisabled ? colors.surface : colors.background },
|
|
870
|
+
borderColorStyle,
|
|
755
871
|
inputWrapperStyle
|
|
756
872
|
]
|
|
757
873
|
},
|
|
@@ -761,31 +877,36 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
761
877
|
{
|
|
762
878
|
style: [
|
|
763
879
|
styles4.input,
|
|
764
|
-
{
|
|
765
|
-
color: colors.foreground
|
|
766
|
-
},
|
|
880
|
+
{ color: colors.foreground },
|
|
767
881
|
webInputResetStyle,
|
|
768
882
|
style
|
|
769
883
|
],
|
|
770
884
|
onFocus: (e) => {
|
|
771
885
|
setFocused(true);
|
|
772
|
-
Animated.timing(focusAnim, { toValue: 1, duration: 120, easing: Easing$1.out(Easing$1.ease), useNativeDriver: false }).start();
|
|
773
886
|
onFocus?.(e);
|
|
774
887
|
},
|
|
775
888
|
onBlur: (e) => {
|
|
776
889
|
setFocused(false);
|
|
777
|
-
Animated.timing(focusAnim, { toValue: 0, duration: 80, easing: Easing$1.out(Easing$1.ease), useNativeDriver: false }).start();
|
|
778
890
|
onBlur?.(e);
|
|
779
891
|
},
|
|
780
892
|
placeholderTextColor: colors.foregroundMuted,
|
|
781
893
|
allowFontScaling: true,
|
|
782
894
|
secureTextEntry: effectiveSecure,
|
|
783
895
|
editable: isDisabled ? false : editable,
|
|
896
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
784
897
|
...props
|
|
785
898
|
}
|
|
786
899
|
),
|
|
787
900
|
effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */ React26.createElement(Text, { style: [styles4.suffixText, { color: colors.foregroundMuted }, suffixStyle], allowFontScaling: true }, effectiveSuffix) : /* @__PURE__ */ React26.createElement(View, { style: styles4.suffixContainer }, effectiveSuffix) : null
|
|
788
|
-
), error ? /* @__PURE__ */ React26.createElement(
|
|
901
|
+
), error ? /* @__PURE__ */ React26.createElement(
|
|
902
|
+
Text,
|
|
903
|
+
{
|
|
904
|
+
style: [styles4.helperText, { color: colors.destructive }],
|
|
905
|
+
allowFontScaling: true,
|
|
906
|
+
accessibilityLiveRegion: "polite"
|
|
907
|
+
},
|
|
908
|
+
error
|
|
909
|
+
) : null, !error && hint ? /* @__PURE__ */ React26.createElement(Text, { style: [styles4.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
|
|
789
910
|
}
|
|
790
911
|
var styles4 = StyleSheet.create({
|
|
791
912
|
container: {
|
|
@@ -797,7 +918,6 @@ var styles4 = StyleSheet.create({
|
|
|
797
918
|
label: {
|
|
798
919
|
fontFamily: "Poppins-Medium",
|
|
799
920
|
fontSize: ms(14)
|
|
800
|
-
// caption size for input labels
|
|
801
921
|
},
|
|
802
922
|
inputWrapper: {
|
|
803
923
|
flexDirection: "row",
|
|
@@ -894,30 +1014,14 @@ var styles5 = StyleSheet.create({
|
|
|
894
1014
|
fontFamily: "Poppins-Medium"
|
|
895
1015
|
}
|
|
896
1016
|
});
|
|
897
|
-
|
|
898
|
-
function Card({ children, variant = "elevated", onPress, style }) {
|
|
1017
|
+
function Card({ children, variant = "elevated", onPress, style, accessibilityLabel }) {
|
|
899
1018
|
const { colors } = useTheme();
|
|
900
|
-
const
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
stiffness: 400,
|
|
907
|
-
damping: 30,
|
|
908
|
-
mass: 1
|
|
909
|
-
}).start();
|
|
910
|
-
};
|
|
911
|
-
const handlePressOut = () => {
|
|
912
|
-
if (!onPress) return;
|
|
913
|
-
Animated.spring(scale2, {
|
|
914
|
-
toValue: 1,
|
|
915
|
-
useNativeDriver: nativeDriver3,
|
|
916
|
-
stiffness: 250,
|
|
917
|
-
damping: 24,
|
|
918
|
-
mass: 1
|
|
919
|
-
}).start();
|
|
920
|
-
};
|
|
1019
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
1020
|
+
pressScale: PRESS_SCALE.card,
|
|
1021
|
+
pressInSpring: SPRINGS.surfacePressIn,
|
|
1022
|
+
pressOutSpring: SPRINGS.surfacePressOut,
|
|
1023
|
+
disabled: !onPress
|
|
1024
|
+
});
|
|
921
1025
|
const handlePress = () => {
|
|
922
1026
|
if (!onPress) return;
|
|
923
1027
|
impactLight();
|
|
@@ -948,14 +1052,16 @@ function Card({ children, variant = "elevated", onPress, style }) {
|
|
|
948
1052
|
}[variant];
|
|
949
1053
|
const cardContent = /* @__PURE__ */ React26.createElement(View, { style: [styles6.card, variantStyle, style] }, children);
|
|
950
1054
|
if (onPress) {
|
|
951
|
-
return /* @__PURE__ */ React26.createElement(
|
|
1055
|
+
return /* @__PURE__ */ React26.createElement(Animated9.View, { style: animatedStyle, ...hoverHandlers }, /* @__PURE__ */ React26.createElement(
|
|
952
1056
|
TouchableOpacity,
|
|
953
1057
|
{
|
|
954
1058
|
onPress: handlePress,
|
|
955
|
-
onPressIn
|
|
956
|
-
onPressOut
|
|
1059
|
+
onPressIn,
|
|
1060
|
+
onPressOut,
|
|
957
1061
|
activeOpacity: 1,
|
|
958
|
-
touchSoundDisabled: true
|
|
1062
|
+
touchSoundDisabled: true,
|
|
1063
|
+
accessibilityRole: "button",
|
|
1064
|
+
accessibilityLabel
|
|
959
1065
|
},
|
|
960
1066
|
cardContent
|
|
961
1067
|
));
|
|
@@ -982,7 +1088,6 @@ function CardFooter({ children, style }) {
|
|
|
982
1088
|
var styles6 = StyleSheet.create({
|
|
983
1089
|
card: {
|
|
984
1090
|
borderRadius: RADIUS.md,
|
|
985
|
-
// 14px — Airbnb property card spec
|
|
986
1091
|
borderWidth: 1
|
|
987
1092
|
},
|
|
988
1093
|
header: {
|
|
@@ -1080,20 +1185,19 @@ function Skeleton({
|
|
|
1080
1185
|
style
|
|
1081
1186
|
}) {
|
|
1082
1187
|
const { colors, colorScheme } = useTheme();
|
|
1083
|
-
const
|
|
1188
|
+
const shimmer = useSharedValue(0);
|
|
1084
1189
|
const [containerWidth, setContainerWidth] = useState(300);
|
|
1085
1190
|
const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(255,255,255,0.7)";
|
|
1086
1191
|
useEffect(() => {
|
|
1087
|
-
|
|
1088
|
-
|
|
1192
|
+
shimmer.value = withRepeat(
|
|
1193
|
+
withTiming(1, { duration: TIMINGS.shimmer.duration, easing: Easing.linear }),
|
|
1194
|
+
-1,
|
|
1195
|
+
false
|
|
1089
1196
|
);
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
inputRange: [0, 1],
|
|
1095
|
-
outputRange: [-containerWidth, containerWidth]
|
|
1096
|
-
});
|
|
1197
|
+
}, [shimmer]);
|
|
1198
|
+
const shimmerStyle = useAnimatedStyle(() => ({
|
|
1199
|
+
transform: [{ translateX: -containerWidth + shimmer.value * (containerWidth * 2) }]
|
|
1200
|
+
}));
|
|
1097
1201
|
const resolvedWidth = preset === "circle" ? s(diameter) : preset === "text" ? "60%" : width;
|
|
1098
1202
|
const resolvedHeight = preset === "circle" ? s(diameter) : preset === "text" ? 14 : height;
|
|
1099
1203
|
const resolvedRadius = preset === "circle" ? 9999 : preset === "text" ? 4 : borderRadius;
|
|
@@ -1105,9 +1209,12 @@ function Skeleton({
|
|
|
1105
1209
|
{ width: resolvedWidth, height: resolvedHeight, borderRadius: resolvedRadius, backgroundColor: colors.surface },
|
|
1106
1210
|
style
|
|
1107
1211
|
],
|
|
1108
|
-
onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width)
|
|
1212
|
+
onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width),
|
|
1213
|
+
accessibilityRole: "progressbar",
|
|
1214
|
+
accessibilityLabel: "Loading",
|
|
1215
|
+
accessibilityState: { busy: true }
|
|
1109
1216
|
},
|
|
1110
|
-
/* @__PURE__ */ React26.createElement(
|
|
1217
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [StyleSheet.absoluteFill, shimmerStyle] }, /* @__PURE__ */ React26.createElement(
|
|
1111
1218
|
LinearGradient,
|
|
1112
1219
|
{
|
|
1113
1220
|
colors: ["transparent", shimmerHighlight, "transparent"],
|
|
@@ -1253,31 +1360,32 @@ var styles11 = StyleSheet.create({
|
|
|
1253
1360
|
lineHeight: ms(17)
|
|
1254
1361
|
}
|
|
1255
1362
|
});
|
|
1256
|
-
function Progress({ value = 0, max = 100, variant = "default", style }) {
|
|
1363
|
+
function Progress({ value = 0, max = 100, variant = "default", style, accessibilityLabel }) {
|
|
1257
1364
|
const { colors } = useTheme();
|
|
1258
1365
|
const percent = Math.min(Math.max(value / max * 100, 0), 100);
|
|
1259
1366
|
const [trackWidth, setTrackWidth] = useState(0);
|
|
1260
|
-
const animatedWidth =
|
|
1367
|
+
const animatedWidth = useSharedValue(0);
|
|
1261
1368
|
useEffect(() => {
|
|
1262
1369
|
if (trackWidth === 0) return;
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
}).start();
|
|
1269
|
-
}, [percent, trackWidth]);
|
|
1370
|
+
animatedWidth.value = withSpring(percent / 100 * trackWidth, SPRINGS.glide);
|
|
1371
|
+
}, [percent, trackWidth, animatedWidth]);
|
|
1372
|
+
const indicatorAnimatedStyle = useAnimatedStyle(() => ({
|
|
1373
|
+
width: animatedWidth.value
|
|
1374
|
+
}));
|
|
1270
1375
|
const indicatorColor = variant === "success" ? colors.success : variant === "warning" ? colors.warning : variant === "destructive" ? colors.destructive : colors.primary;
|
|
1271
1376
|
return /* @__PURE__ */ React26.createElement(
|
|
1272
1377
|
View,
|
|
1273
1378
|
{
|
|
1274
1379
|
style: [styles12.track, { backgroundColor: colors.surface }, style],
|
|
1275
|
-
onLayout: (e) => setTrackWidth(e.nativeEvent.layout.width)
|
|
1380
|
+
onLayout: (e) => setTrackWidth(e.nativeEvent.layout.width),
|
|
1381
|
+
accessibilityRole: "progressbar",
|
|
1382
|
+
accessibilityLabel,
|
|
1383
|
+
accessibilityValue: { min: 0, max: 100, now: Math.round(percent) }
|
|
1276
1384
|
},
|
|
1277
1385
|
/* @__PURE__ */ React26.createElement(
|
|
1278
|
-
|
|
1386
|
+
Animated9.View,
|
|
1279
1387
|
{
|
|
1280
|
-
style: [styles12.indicator, {
|
|
1388
|
+
style: [styles12.indicator, { backgroundColor: indicatorColor }, indicatorAnimatedStyle]
|
|
1281
1389
|
}
|
|
1282
1390
|
)
|
|
1283
1391
|
);
|
|
@@ -1394,20 +1502,25 @@ function Textarea({
|
|
|
1394
1502
|
style,
|
|
1395
1503
|
onFocus,
|
|
1396
1504
|
onBlur,
|
|
1505
|
+
accessibilityLabel,
|
|
1397
1506
|
...props
|
|
1398
1507
|
}) {
|
|
1399
1508
|
const { colors } = useTheme();
|
|
1400
1509
|
const [focused, setFocused] = useState(false);
|
|
1510
|
+
const focusProgress = useColorTransition(focused, {
|
|
1511
|
+
duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
|
|
1512
|
+
});
|
|
1401
1513
|
const resolvedPrefixIcon = prefixIcon ? renderIcon(prefixIcon, ms(16), prefixIconColor ?? colors.foregroundMuted) : prefixIconNode;
|
|
1514
|
+
const borderColorStyle = useAnimatedStyle(() => ({
|
|
1515
|
+
borderColor: error ? colors.destructive : interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary])
|
|
1516
|
+
}));
|
|
1402
1517
|
return /* @__PURE__ */ React26.createElement(View, { style: [styles14.container, containerStyle] }, label ? /* @__PURE__ */ React26.createElement(Text, { style: [styles14.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React26.createElement(
|
|
1403
|
-
View,
|
|
1518
|
+
Animated9.View,
|
|
1404
1519
|
{
|
|
1405
1520
|
style: [
|
|
1406
1521
|
styles14.inputWrapper,
|
|
1407
|
-
{
|
|
1408
|
-
|
|
1409
|
-
backgroundColor: colors.background
|
|
1410
|
-
}
|
|
1522
|
+
{ backgroundColor: colors.background },
|
|
1523
|
+
borderColorStyle
|
|
1411
1524
|
]
|
|
1412
1525
|
},
|
|
1413
1526
|
resolvedPrefixIcon ? /* @__PURE__ */ React26.createElement(View, { style: styles14.prefixIcon }, resolvedPrefixIcon) : null,
|
|
@@ -1436,10 +1549,19 @@ function Textarea({
|
|
|
1436
1549
|
},
|
|
1437
1550
|
placeholderTextColor: colors.foregroundMuted,
|
|
1438
1551
|
allowFontScaling: true,
|
|
1552
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
1439
1553
|
...props
|
|
1440
1554
|
}
|
|
1441
1555
|
)
|
|
1442
|
-
), error ? /* @__PURE__ */ React26.createElement(
|
|
1556
|
+
), error ? /* @__PURE__ */ React26.createElement(
|
|
1557
|
+
Text,
|
|
1558
|
+
{
|
|
1559
|
+
style: [styles14.helperText, { color: colors.destructive }],
|
|
1560
|
+
allowFontScaling: true,
|
|
1561
|
+
accessibilityLiveRegion: "polite"
|
|
1562
|
+
},
|
|
1563
|
+
error
|
|
1564
|
+
) : null, !error && hint ? /* @__PURE__ */ React26.createElement(Text, { style: [styles14.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
|
|
1443
1565
|
}
|
|
1444
1566
|
var styles14 = StyleSheet.create({
|
|
1445
1567
|
container: {
|
|
@@ -1452,7 +1574,7 @@ var styles14 = StyleSheet.create({
|
|
|
1452
1574
|
marginBottom: vs(2)
|
|
1453
1575
|
},
|
|
1454
1576
|
inputWrapper: {
|
|
1455
|
-
borderWidth:
|
|
1577
|
+
borderWidth: 2,
|
|
1456
1578
|
borderRadius: 8,
|
|
1457
1579
|
paddingHorizontal: s(14),
|
|
1458
1580
|
paddingVertical: vs(11),
|
|
@@ -1477,47 +1599,27 @@ var styles14 = StyleSheet.create({
|
|
|
1477
1599
|
marginTop: vs(4)
|
|
1478
1600
|
}
|
|
1479
1601
|
});
|
|
1480
|
-
var nativeDriver4 = Platform.OS !== "web";
|
|
1481
1602
|
function Checkbox({
|
|
1482
1603
|
checked = false,
|
|
1483
1604
|
onCheckedChange,
|
|
1484
1605
|
label,
|
|
1485
1606
|
disabled,
|
|
1486
|
-
style
|
|
1607
|
+
style,
|
|
1608
|
+
accessibilityLabel
|
|
1487
1609
|
}) {
|
|
1488
1610
|
const { colors } = useTheme();
|
|
1489
|
-
const
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
useEffect(() => {
|
|
1493
|
-
Animated.parallel([
|
|
1494
|
-
Animated.timing(bgOpacity, {
|
|
1495
|
-
toValue: checked ? 1 : 0,
|
|
1496
|
-
duration: 150,
|
|
1497
|
-
useNativeDriver: false
|
|
1498
|
-
}),
|
|
1499
|
-
Animated.timing(checkOpacity, {
|
|
1500
|
-
toValue: checked ? 1 : 0,
|
|
1501
|
-
duration: 120,
|
|
1502
|
-
useNativeDriver: false
|
|
1503
|
-
})
|
|
1504
|
-
]).start();
|
|
1505
|
-
}, [checked, bgOpacity, checkOpacity]);
|
|
1506
|
-
const borderColor = bgOpacity.interpolate({
|
|
1507
|
-
inputRange: [0, 1],
|
|
1508
|
-
outputRange: [colors.border, colors.primary]
|
|
1611
|
+
const { animatedStyle: scaleStyle, onPressIn, onPressOut } = usePressScale({
|
|
1612
|
+
pressScale: PRESS_SCALE.button,
|
|
1613
|
+
disabled
|
|
1509
1614
|
});
|
|
1510
|
-
const
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
};
|
|
1518
|
-
const handlePressOut = () => {
|
|
1519
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver4, speed: 40, bounciness: 0 }).start();
|
|
1520
|
-
};
|
|
1615
|
+
const progress = useColorTransition(checked);
|
|
1616
|
+
const boxStyle = useAnimatedStyle(() => ({
|
|
1617
|
+
borderColor: interpolateColor(progress.value, [0, 1], [colors.border, colors.primary]),
|
|
1618
|
+
backgroundColor: interpolateColor(progress.value, [0, 1], ["transparent", colors.primary])
|
|
1619
|
+
}));
|
|
1620
|
+
const checkStyle = useAnimatedStyle(() => ({
|
|
1621
|
+
opacity: withTiming(checked ? 1 : 0, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
|
|
1622
|
+
}));
|
|
1521
1623
|
return /* @__PURE__ */ React26.createElement(
|
|
1522
1624
|
TouchableOpacity,
|
|
1523
1625
|
{
|
|
@@ -1526,25 +1628,21 @@ function Checkbox({
|
|
|
1526
1628
|
selectionAsync();
|
|
1527
1629
|
onCheckedChange?.(!checked);
|
|
1528
1630
|
},
|
|
1529
|
-
onPressIn
|
|
1530
|
-
onPressOut
|
|
1631
|
+
onPressIn,
|
|
1632
|
+
onPressOut,
|
|
1531
1633
|
disabled,
|
|
1532
1634
|
activeOpacity: 1,
|
|
1533
|
-
touchSoundDisabled: true
|
|
1635
|
+
touchSoundDisabled: true,
|
|
1636
|
+
accessibilityRole: "checkbox",
|
|
1637
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
1638
|
+
accessibilityState: { checked, disabled: !!disabled }
|
|
1534
1639
|
},
|
|
1535
|
-
/* @__PURE__ */ React26.createElement(
|
|
1536
|
-
|
|
1640
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: scaleStyle }, /* @__PURE__ */ React26.createElement(
|
|
1641
|
+
Animated9.View,
|
|
1537
1642
|
{
|
|
1538
|
-
style: [
|
|
1539
|
-
styles15.box,
|
|
1540
|
-
{
|
|
1541
|
-
borderColor,
|
|
1542
|
-
backgroundColor,
|
|
1543
|
-
opacity: disabled ? 0.45 : 1
|
|
1544
|
-
}
|
|
1545
|
-
]
|
|
1643
|
+
style: [styles15.box, { opacity: disabled ? 0.45 : 1 }, boxStyle]
|
|
1546
1644
|
},
|
|
1547
|
-
/* @__PURE__ */ React26.createElement(
|
|
1645
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: checkStyle }, /* @__PURE__ */ React26.createElement(View, { style: [styles15.checkmark, { borderColor: colors.primaryForeground }] }))
|
|
1548
1646
|
)),
|
|
1549
1647
|
label ? /* @__PURE__ */ React26.createElement(
|
|
1550
1648
|
Text,
|
|
@@ -1583,47 +1681,34 @@ var styles15 = StyleSheet.create({
|
|
|
1583
1681
|
lineHeight: mvs(20)
|
|
1584
1682
|
}
|
|
1585
1683
|
});
|
|
1586
|
-
var nativeDriver5 = Platform.OS !== "web";
|
|
1587
1684
|
var TRACK_WIDTH = s(52);
|
|
1588
1685
|
var TRACK_HEIGHT = s(30);
|
|
1589
1686
|
var THUMB_SIZE = s(24);
|
|
1590
1687
|
var THUMB_OFFSET = s(3);
|
|
1591
1688
|
var THUMB_TRAVEL = TRACK_WIDTH - THUMB_SIZE - THUMB_OFFSET * 2;
|
|
1592
1689
|
var ICON_SIZE = s(13);
|
|
1593
|
-
function Switch({ checked = false, onCheckedChange, disabled, style }) {
|
|
1690
|
+
function Switch({ checked = false, onCheckedChange, disabled, style, accessibilityLabel }) {
|
|
1594
1691
|
const { colors } = useTheme();
|
|
1595
|
-
const
|
|
1596
|
-
const trackOpacity = useRef(new Animated.Value(checked ? 1 : 0)).current;
|
|
1597
|
-
const checkOpacity = useRef(new Animated.Value(checked ? 1 : 0)).current;
|
|
1598
|
-
const crossOpacity = useRef(new Animated.Value(checked ? 0 : 1)).current;
|
|
1692
|
+
const progress = useSharedValue(checked ? 1 : 0);
|
|
1599
1693
|
useEffect(() => {
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
duration: 120,
|
|
1619
|
-
useNativeDriver: true
|
|
1620
|
-
})
|
|
1621
|
-
]).start();
|
|
1622
|
-
}, [checked, translateX, trackOpacity, checkOpacity, crossOpacity]);
|
|
1623
|
-
const trackColor = trackOpacity.interpolate({
|
|
1624
|
-
inputRange: [0, 1],
|
|
1625
|
-
outputRange: [colors.surface, colors.primary]
|
|
1626
|
-
});
|
|
1694
|
+
progress.value = withSpring(checked ? 1 : 0, SPRINGS.elastic);
|
|
1695
|
+
}, [checked, progress]);
|
|
1696
|
+
const thumbStyle = useAnimatedStyle(() => ({
|
|
1697
|
+
transform: [{ translateX: progress.value * THUMB_TRAVEL }]
|
|
1698
|
+
}));
|
|
1699
|
+
const trackStyle = useAnimatedStyle(() => ({
|
|
1700
|
+
backgroundColor: interpolateColor(
|
|
1701
|
+
progress.value,
|
|
1702
|
+
[0, 1],
|
|
1703
|
+
[colors.surfaceStrong, colors.primary]
|
|
1704
|
+
)
|
|
1705
|
+
}));
|
|
1706
|
+
const checkIconStyle = useAnimatedStyle(() => ({
|
|
1707
|
+
opacity: withTiming(checked ? 1 : 0, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
|
|
1708
|
+
}));
|
|
1709
|
+
const crossIconStyle = useAnimatedStyle(() => ({
|
|
1710
|
+
opacity: withTiming(checked ? 0 : 1, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
|
|
1711
|
+
}));
|
|
1627
1712
|
return /* @__PURE__ */ React26.createElement(View, { style: [{ opacity: disabled ? 0.45 : 1 }, style] }, /* @__PURE__ */ React26.createElement(
|
|
1628
1713
|
TouchableOpacity,
|
|
1629
1714
|
{
|
|
@@ -1634,29 +1719,25 @@ function Switch({ checked = false, onCheckedChange, disabled, style }) {
|
|
|
1634
1719
|
disabled,
|
|
1635
1720
|
activeOpacity: 0.8,
|
|
1636
1721
|
touchSoundDisabled: true,
|
|
1637
|
-
|
|
1722
|
+
accessibilityRole: "switch",
|
|
1723
|
+
accessibilityLabel,
|
|
1724
|
+
accessibilityState: { checked, disabled: !!disabled }
|
|
1638
1725
|
},
|
|
1639
|
-
/* @__PURE__ */ React26.createElement(
|
|
1640
|
-
|
|
1726
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles16.track, trackStyle] }, /* @__PURE__ */ React26.createElement(
|
|
1727
|
+
Animated9.View,
|
|
1641
1728
|
{
|
|
1642
|
-
style: [
|
|
1643
|
-
styles16.thumb,
|
|
1644
|
-
{ backgroundColor: colors.primaryForeground, transform: [{ translateX }] }
|
|
1645
|
-
]
|
|
1729
|
+
style: [styles16.thumb, { backgroundColor: colors.primaryForeground }, thumbStyle]
|
|
1646
1730
|
},
|
|
1647
|
-
/* @__PURE__ */ React26.createElement(
|
|
1648
|
-
/* @__PURE__ */ React26.createElement(
|
|
1731
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles16.iconWrapper, checkIconStyle] }, /* @__PURE__ */ React26.createElement(Feather$1, { name: "check", size: ICON_SIZE, color: colors.primary })),
|
|
1732
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles16.iconWrapper, crossIconStyle] }, /* @__PURE__ */ React26.createElement(Feather$1, { name: "x", size: ICON_SIZE, color: colors.foregroundMuted }))
|
|
1649
1733
|
))
|
|
1650
1734
|
));
|
|
1651
1735
|
}
|
|
1652
1736
|
var styles16 = StyleSheet.create({
|
|
1653
|
-
wrapper: {},
|
|
1654
1737
|
track: {
|
|
1655
1738
|
width: TRACK_WIDTH,
|
|
1656
1739
|
height: TRACK_HEIGHT,
|
|
1657
1740
|
borderRadius: TRACK_HEIGHT / 2
|
|
1658
|
-
// No justifyContent/alignItems — thumb uses absolute positioning
|
|
1659
|
-
// so the track's flex layout doesn't interfere with translateX animation
|
|
1660
1741
|
},
|
|
1661
1742
|
thumb: {
|
|
1662
1743
|
position: "absolute",
|
|
@@ -1677,7 +1758,6 @@ var styles16 = StyleSheet.create({
|
|
|
1677
1758
|
position: "absolute"
|
|
1678
1759
|
}
|
|
1679
1760
|
});
|
|
1680
|
-
var nativeDriver6 = Platform.OS !== "web";
|
|
1681
1761
|
var sizeStyles = {
|
|
1682
1762
|
sm: { paddingHorizontal: s(12), paddingVertical: vs(8), minWidth: s(40), minHeight: vs(40) },
|
|
1683
1763
|
md: { paddingHorizontal: s(16), paddingVertical: vs(12), minWidth: s(44), minHeight: vs(44) },
|
|
@@ -1698,38 +1778,23 @@ function Toggle({
|
|
|
1698
1778
|
activeIconColor,
|
|
1699
1779
|
disabled,
|
|
1700
1780
|
style,
|
|
1781
|
+
accessibilityLabel,
|
|
1701
1782
|
...props
|
|
1702
1783
|
}) {
|
|
1703
1784
|
const { colors } = useTheme();
|
|
1704
|
-
const
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
Animated.timing(pressAnim, {
|
|
1708
|
-
toValue: pressed ? 1 : 0,
|
|
1709
|
-
duration: 150,
|
|
1710
|
-
easing: Easing$1.out(Easing$1.ease),
|
|
1711
|
-
useNativeDriver: false
|
|
1712
|
-
}).start();
|
|
1713
|
-
}, [pressed, pressAnim]);
|
|
1714
|
-
const handlePressIn = () => {
|
|
1715
|
-
if (disabled) return;
|
|
1716
|
-
Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver6, stiffness: 600, damping: 35, mass: 0.8 }).start();
|
|
1717
|
-
};
|
|
1718
|
-
const handlePressOut = () => {
|
|
1719
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver6, stiffness: 280, damping: 22, mass: 0.8 }).start();
|
|
1720
|
-
};
|
|
1721
|
-
const borderColor = pressAnim.interpolate({
|
|
1722
|
-
inputRange: [0, 1],
|
|
1723
|
-
outputRange: [variant === "outline" ? colors.border : "transparent", colors.primary]
|
|
1724
|
-
});
|
|
1725
|
-
const backgroundColor = pressAnim.interpolate({
|
|
1726
|
-
inputRange: [0, 1],
|
|
1727
|
-
outputRange: ["transparent", colors.surfaceStrong]
|
|
1728
|
-
});
|
|
1729
|
-
const textColor = pressAnim.interpolate({
|
|
1730
|
-
inputRange: [0, 1],
|
|
1731
|
-
outputRange: [colors.foreground, colors.primary]
|
|
1785
|
+
const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
1786
|
+
pressScale: PRESS_SCALE.button,
|
|
1787
|
+
disabled
|
|
1732
1788
|
});
|
|
1789
|
+
const progress = useColorTransition(pressed);
|
|
1790
|
+
const inactiveBorder = variant === "outline" ? colors.border : "transparent";
|
|
1791
|
+
const surfaceStyle = useAnimatedStyle(() => ({
|
|
1792
|
+
borderColor: interpolateColor(progress.value, [0, 1], [inactiveBorder, colors.primary]),
|
|
1793
|
+
backgroundColor: interpolateColor(progress.value, [0, 1], ["transparent", colors.surfaceStrong])
|
|
1794
|
+
}));
|
|
1795
|
+
const textStyle = useAnimatedStyle(() => ({
|
|
1796
|
+
color: interpolateColor(progress.value, [0, 1], [colors.foreground, colors.primary])
|
|
1797
|
+
}));
|
|
1733
1798
|
const iconSize = iconSizeMap2[size];
|
|
1734
1799
|
const LeftIcon = () => {
|
|
1735
1800
|
const renderProp = (prop) => {
|
|
@@ -1748,32 +1813,43 @@ function Toggle({
|
|
|
1748
1813
|
if (custom) return /* @__PURE__ */ React26.createElement(React26.Fragment, null, custom);
|
|
1749
1814
|
return /* @__PURE__ */ React26.createElement(FontAwesome5$1, { name: "circle", size: iconSize, color: colors.foregroundMuted });
|
|
1750
1815
|
};
|
|
1751
|
-
return /* @__PURE__ */ React26.createElement(
|
|
1752
|
-
|
|
1816
|
+
return /* @__PURE__ */ React26.createElement(
|
|
1817
|
+
Animated9.View,
|
|
1753
1818
|
{
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
onPressedChange?.(!pressed);
|
|
1757
|
-
},
|
|
1758
|
-
onPressIn: handlePressIn,
|
|
1759
|
-
onPressOut: handlePressOut,
|
|
1760
|
-
disabled,
|
|
1761
|
-
activeOpacity: 1,
|
|
1762
|
-
touchSoundDisabled: true,
|
|
1763
|
-
...props
|
|
1819
|
+
style: [scaleStyle, disabled && styles17.disabled, style],
|
|
1820
|
+
...hoverHandlers
|
|
1764
1821
|
},
|
|
1765
1822
|
/* @__PURE__ */ React26.createElement(
|
|
1766
|
-
|
|
1823
|
+
TouchableOpacity,
|
|
1767
1824
|
{
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1825
|
+
onPress: () => {
|
|
1826
|
+
selectionAsync();
|
|
1827
|
+
onPressedChange?.(!pressed);
|
|
1828
|
+
},
|
|
1829
|
+
onPressIn,
|
|
1830
|
+
onPressOut,
|
|
1831
|
+
disabled,
|
|
1832
|
+
activeOpacity: 1,
|
|
1833
|
+
touchSoundDisabled: true,
|
|
1834
|
+
accessibilityRole: "button",
|
|
1835
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
1836
|
+
accessibilityState: { selected: pressed, disabled: !!disabled },
|
|
1837
|
+
...props
|
|
1773
1838
|
},
|
|
1774
|
-
/* @__PURE__ */ React26.createElement(
|
|
1839
|
+
/* @__PURE__ */ React26.createElement(
|
|
1840
|
+
Animated9.View,
|
|
1841
|
+
{
|
|
1842
|
+
style: [
|
|
1843
|
+
styles17.base,
|
|
1844
|
+
sizeStyles[size],
|
|
1845
|
+
{ borderWidth: 2 },
|
|
1846
|
+
surfaceStyle
|
|
1847
|
+
]
|
|
1848
|
+
},
|
|
1849
|
+
/* @__PURE__ */ React26.createElement(View, { style: styles17.inner }, /* @__PURE__ */ React26.createElement(LeftIcon, null), label ? /* @__PURE__ */ React26.createElement(Animated9.Text, { style: [styles17.label, textStyle], allowFontScaling: true }, label) : null)
|
|
1850
|
+
)
|
|
1775
1851
|
)
|
|
1776
|
-
)
|
|
1852
|
+
);
|
|
1777
1853
|
}
|
|
1778
1854
|
var styles17 = StyleSheet.create({
|
|
1779
1855
|
base: {
|
|
@@ -1793,21 +1869,28 @@ var styles17 = StyleSheet.create({
|
|
|
1793
1869
|
fontSize: ms(14)
|
|
1794
1870
|
}
|
|
1795
1871
|
});
|
|
1796
|
-
var nativeDriver7 = Platform.OS !== "web";
|
|
1797
1872
|
function RadioItem({
|
|
1798
1873
|
option,
|
|
1799
1874
|
selected,
|
|
1800
1875
|
onSelect
|
|
1801
1876
|
}) {
|
|
1802
1877
|
const { colors } = useTheme();
|
|
1803
|
-
const
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
const
|
|
1809
|
-
|
|
1810
|
-
|
|
1878
|
+
const { animatedStyle: scaleStyle, onPressIn, onPressOut } = usePressScale({
|
|
1879
|
+
pressScale: PRESS_SCALE.button,
|
|
1880
|
+
disabled: option.disabled
|
|
1881
|
+
});
|
|
1882
|
+
const colorProgress = useColorTransition(selected);
|
|
1883
|
+
const dotScale = useSharedValue(selected ? 1 : 0);
|
|
1884
|
+
useEffect(() => {
|
|
1885
|
+
dotScale.value = withSpring(selected ? 1 : 0, SPRINGS.elastic);
|
|
1886
|
+
}, [selected, dotScale]);
|
|
1887
|
+
const radioStyle = useAnimatedStyle(() => ({
|
|
1888
|
+
borderColor: interpolateColor(colorProgress.value, [0, 1], [colors.border, colors.primary])
|
|
1889
|
+
}));
|
|
1890
|
+
const dotStyle = useAnimatedStyle(() => ({
|
|
1891
|
+
transform: [{ scale: dotScale.value }],
|
|
1892
|
+
opacity: dotScale.value
|
|
1893
|
+
}));
|
|
1811
1894
|
return /* @__PURE__ */ React26.createElement(
|
|
1812
1895
|
TouchableOpacity,
|
|
1813
1896
|
{
|
|
@@ -1818,26 +1901,26 @@ function RadioItem({
|
|
|
1818
1901
|
onSelect();
|
|
1819
1902
|
}
|
|
1820
1903
|
},
|
|
1821
|
-
onPressIn
|
|
1822
|
-
onPressOut
|
|
1904
|
+
onPressIn,
|
|
1905
|
+
onPressOut,
|
|
1823
1906
|
activeOpacity: 1,
|
|
1824
1907
|
touchSoundDisabled: true,
|
|
1825
|
-
disabled: option.disabled
|
|
1908
|
+
disabled: option.disabled,
|
|
1909
|
+
accessibilityRole: "radio",
|
|
1910
|
+
accessibilityLabel: option.label,
|
|
1911
|
+
accessibilityState: { checked: selected, disabled: !!option.disabled }
|
|
1826
1912
|
},
|
|
1827
|
-
/* @__PURE__ */ React26.createElement(
|
|
1828
|
-
|
|
1913
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: scaleStyle }, /* @__PURE__ */ React26.createElement(
|
|
1914
|
+
Animated9.View,
|
|
1829
1915
|
{
|
|
1830
1916
|
style: [
|
|
1831
1917
|
styles18.radio,
|
|
1832
|
-
{
|
|
1833
|
-
|
|
1834
|
-
opacity: option.disabled ? 0.45 : 1,
|
|
1835
|
-
transform: [{ scale: scale2 }]
|
|
1836
|
-
}
|
|
1918
|
+
{ opacity: option.disabled ? 0.45 : 1 },
|
|
1919
|
+
radioStyle
|
|
1837
1920
|
]
|
|
1838
1921
|
},
|
|
1839
|
-
|
|
1840
|
-
),
|
|
1922
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles18.dot, { backgroundColor: colors.primary }, dotStyle] })
|
|
1923
|
+
)),
|
|
1841
1924
|
/* @__PURE__ */ React26.createElement(
|
|
1842
1925
|
Text,
|
|
1843
1926
|
{
|
|
@@ -1856,17 +1939,26 @@ function RadioGroup({
|
|
|
1856
1939
|
value,
|
|
1857
1940
|
onValueChange,
|
|
1858
1941
|
orientation = "vertical",
|
|
1859
|
-
style
|
|
1942
|
+
style,
|
|
1943
|
+
accessibilityLabel
|
|
1860
1944
|
}) {
|
|
1861
|
-
return /* @__PURE__ */ React26.createElement(
|
|
1862
|
-
|
|
1945
|
+
return /* @__PURE__ */ React26.createElement(
|
|
1946
|
+
View,
|
|
1863
1947
|
{
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1948
|
+
style: [styles18.container, orientation === "horizontal" && styles18.horizontal, style],
|
|
1949
|
+
accessibilityRole: "radiogroup",
|
|
1950
|
+
accessibilityLabel
|
|
1951
|
+
},
|
|
1952
|
+
options.map((option) => /* @__PURE__ */ React26.createElement(
|
|
1953
|
+
RadioItem,
|
|
1954
|
+
{
|
|
1955
|
+
key: option.value,
|
|
1956
|
+
option,
|
|
1957
|
+
selected: option.value === value,
|
|
1958
|
+
onSelect: () => onValueChange?.(option.value)
|
|
1959
|
+
}
|
|
1960
|
+
))
|
|
1961
|
+
);
|
|
1870
1962
|
}
|
|
1871
1963
|
var styles18 = StyleSheet.create({
|
|
1872
1964
|
container: {
|
|
@@ -1900,7 +1992,6 @@ var styles18 = StyleSheet.create({
|
|
|
1900
1992
|
lineHeight: mvs(20)
|
|
1901
1993
|
}
|
|
1902
1994
|
});
|
|
1903
|
-
var nativeDriver8 = Platform.OS !== "web";
|
|
1904
1995
|
function TabTrigger({
|
|
1905
1996
|
tab,
|
|
1906
1997
|
isActive,
|
|
@@ -1909,13 +2000,9 @@ function TabTrigger({
|
|
|
1909
2000
|
variant
|
|
1910
2001
|
}) {
|
|
1911
2002
|
const { colors } = useTheme();
|
|
1912
|
-
const
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
};
|
|
1916
|
-
const handlePressOut = () => {
|
|
1917
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver8, stiffness: 280, damping: 22, mass: 0.8 }).start();
|
|
1918
|
-
};
|
|
2003
|
+
const { animatedStyle, onPressIn, onPressOut } = usePressScale({
|
|
2004
|
+
pressScale: PRESS_SCALE.button
|
|
2005
|
+
});
|
|
1919
2006
|
const isUnderline = variant === "underline";
|
|
1920
2007
|
return /* @__PURE__ */ React26.createElement(
|
|
1921
2008
|
TouchableOpacity,
|
|
@@ -1926,13 +2013,16 @@ function TabTrigger({
|
|
|
1926
2013
|
isUnderline && isActive && { borderBottomColor: colors.primary }
|
|
1927
2014
|
],
|
|
1928
2015
|
onPress,
|
|
1929
|
-
onPressIn
|
|
1930
|
-
onPressOut
|
|
2016
|
+
onPressIn,
|
|
2017
|
+
onPressOut,
|
|
1931
2018
|
onLayout,
|
|
1932
2019
|
activeOpacity: 1,
|
|
1933
|
-
touchSoundDisabled: true
|
|
2020
|
+
touchSoundDisabled: true,
|
|
2021
|
+
accessibilityRole: "tab",
|
|
2022
|
+
accessibilityState: { selected: isActive },
|
|
2023
|
+
accessibilityLabel: tab.label
|
|
1934
2024
|
},
|
|
1935
|
-
/* @__PURE__ */ React26.createElement(
|
|
2025
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: animatedStyle }, /* @__PURE__ */ React26.createElement(View, { style: styles19.triggerInner }, tab.icon ? typeof tab.icon === "function" ? tab.icon(isActive) : tab.icon : null, /* @__PURE__ */ React26.createElement(
|
|
1936
2026
|
Text,
|
|
1937
2027
|
{
|
|
1938
2028
|
style: [
|
|
@@ -1951,20 +2041,18 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
|
|
|
1951
2041
|
const { colors } = useTheme();
|
|
1952
2042
|
const active = value ?? internal;
|
|
1953
2043
|
const tabLayouts = useRef({});
|
|
1954
|
-
const pillX =
|
|
1955
|
-
const pillWidth =
|
|
2044
|
+
const pillX = useSharedValue(0);
|
|
2045
|
+
const pillWidth = useSharedValue(0);
|
|
1956
2046
|
const initialised = useRef(false);
|
|
1957
2047
|
const animatePill = (tabValue, animate) => {
|
|
1958
2048
|
const layout = tabLayouts.current[tabValue];
|
|
1959
2049
|
if (!layout) return;
|
|
1960
2050
|
if (animate) {
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
Animated.spring(pillWidth, { toValue: layout.width, useNativeDriver: false, stiffness: 380, damping: 38, mass: 1 })
|
|
1964
|
-
]).start();
|
|
2051
|
+
pillX.value = withSpring(layout.x, SPRINGS.glide);
|
|
2052
|
+
pillWidth.value = withSpring(layout.width, SPRINGS.glide);
|
|
1965
2053
|
} else {
|
|
1966
|
-
pillX.
|
|
1967
|
-
pillWidth.
|
|
2054
|
+
pillX.value = layout.x;
|
|
2055
|
+
pillWidth.value = layout.width;
|
|
1968
2056
|
}
|
|
1969
2057
|
};
|
|
1970
2058
|
useEffect(() => {
|
|
@@ -1975,51 +2063,63 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
|
|
|
1975
2063
|
if (!value) setInternal(v);
|
|
1976
2064
|
onValueChange?.(v);
|
|
1977
2065
|
};
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2066
|
+
const pillAnimatedStyle = useAnimatedStyle(() => ({
|
|
2067
|
+
transform: [{ translateX: pillX.value }],
|
|
2068
|
+
width: pillWidth.value
|
|
2069
|
+
}));
|
|
2070
|
+
return /* @__PURE__ */ React26.createElement(View, { style }, /* @__PURE__ */ React26.createElement(
|
|
2071
|
+
View,
|
|
1982
2072
|
{
|
|
1983
2073
|
style: [
|
|
1984
|
-
styles19.
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2074
|
+
variant === "pill" ? [styles19.list, { backgroundColor: colors.surface }] : styles19.listUnderline
|
|
2075
|
+
],
|
|
2076
|
+
accessibilityRole: "tablist"
|
|
2077
|
+
},
|
|
2078
|
+
variant === "pill" && /* @__PURE__ */ React26.createElement(
|
|
2079
|
+
Animated9.View,
|
|
2080
|
+
{
|
|
2081
|
+
style: [
|
|
2082
|
+
styles19.pill,
|
|
2083
|
+
{
|
|
2084
|
+
backgroundColor: colors.background,
|
|
2085
|
+
position: "absolute",
|
|
2086
|
+
top: 4,
|
|
2087
|
+
bottom: 4,
|
|
2088
|
+
left: 0,
|
|
2089
|
+
borderRadius: 8,
|
|
2090
|
+
shadowColor: "#000",
|
|
2091
|
+
shadowOffset: { width: 0, height: 1 },
|
|
2092
|
+
shadowOpacity: 0.08,
|
|
2093
|
+
shadowRadius: 2,
|
|
2094
|
+
elevation: 2
|
|
2095
|
+
},
|
|
2096
|
+
pillAnimatedStyle
|
|
2097
|
+
]
|
|
2098
|
+
}
|
|
2099
|
+
),
|
|
2100
|
+
tabs.map((tab) => /* @__PURE__ */ React26.createElement(
|
|
2101
|
+
TabTrigger,
|
|
2102
|
+
{
|
|
2103
|
+
key: tab.value,
|
|
2104
|
+
tab,
|
|
2105
|
+
isActive: tab.value === active,
|
|
2106
|
+
onPress: () => handlePress(tab.value),
|
|
2107
|
+
variant,
|
|
2108
|
+
onLayout: (e) => {
|
|
2109
|
+
const { x, width } = e.nativeEvent.layout;
|
|
2110
|
+
tabLayouts.current[tab.value] = { x, width };
|
|
2111
|
+
if (tab.value === active) {
|
|
2112
|
+
animatePill(tab.value, false);
|
|
2113
|
+
initialised.current = true;
|
|
2114
|
+
}
|
|
2015
2115
|
}
|
|
2016
2116
|
}
|
|
2017
|
-
|
|
2018
|
-
)
|
|
2117
|
+
))
|
|
2118
|
+
), children);
|
|
2019
2119
|
}
|
|
2020
2120
|
function TabsContent({ value, activeValue, children, style }) {
|
|
2021
2121
|
if (value !== activeValue) return null;
|
|
2022
|
-
return /* @__PURE__ */ React26.createElement(View, { style }, children);
|
|
2122
|
+
return /* @__PURE__ */ React26.createElement(View, { style, accessibilityRole: "none" }, children);
|
|
2023
2123
|
}
|
|
2024
2124
|
var styles19 = StyleSheet.create({
|
|
2025
2125
|
list: {
|
|
@@ -2068,8 +2168,6 @@ var styles19 = StyleSheet.create({
|
|
|
2068
2168
|
fontSize: ms(14)
|
|
2069
2169
|
}
|
|
2070
2170
|
});
|
|
2071
|
-
var easingExpand = Easing.bezier(0.23, 1, 0.32, 1);
|
|
2072
|
-
var easingCollapse = Easing.in(Easing.ease);
|
|
2073
2171
|
function AccordionItemComponent({
|
|
2074
2172
|
item,
|
|
2075
2173
|
isOpen,
|
|
@@ -2084,14 +2182,14 @@ function AccordionItemComponent({
|
|
|
2084
2182
|
}, [isOpen]);
|
|
2085
2183
|
const derivedHeight = useDerivedValue(
|
|
2086
2184
|
() => withTiming(height.value * Number(isExpanded.value), {
|
|
2087
|
-
duration:
|
|
2088
|
-
easing: isExpanded.value ?
|
|
2185
|
+
duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
|
|
2186
|
+
easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
|
|
2089
2187
|
})
|
|
2090
2188
|
);
|
|
2091
2189
|
const derivedRotation = useDerivedValue(
|
|
2092
2190
|
() => withTiming(isExpanded.value ? 1 : 0, {
|
|
2093
|
-
duration:
|
|
2094
|
-
easing: isExpanded.value ?
|
|
2191
|
+
duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
|
|
2192
|
+
easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
|
|
2095
2193
|
})
|
|
2096
2194
|
);
|
|
2097
2195
|
const bodyStyle = useAnimatedStyle(() => ({
|
|
@@ -2108,11 +2206,14 @@ function AccordionItemComponent({
|
|
|
2108
2206
|
onPress: () => {
|
|
2109
2207
|
selectionAsync();
|
|
2110
2208
|
onToggle();
|
|
2111
|
-
}
|
|
2209
|
+
},
|
|
2210
|
+
accessibilityRole: "button",
|
|
2211
|
+
accessibilityState: { expanded: isOpen },
|
|
2212
|
+
accessibilityLabel: item.trigger
|
|
2112
2213
|
},
|
|
2113
2214
|
/* @__PURE__ */ React26.createElement(View, { style: styles20.triggerContent }, resolvedIcon ? /* @__PURE__ */ React26.createElement(View, { style: styles20.icon }, resolvedIcon) : null, /* @__PURE__ */ React26.createElement(Text, { style: [styles20.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger)),
|
|
2114
|
-
/* @__PURE__ */ React26.createElement(
|
|
2115
|
-
), /* @__PURE__ */ React26.createElement(
|
|
2215
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles20.chevron, rotationStyle] }, /* @__PURE__ */ React26.createElement(Entypo$1, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
|
|
2216
|
+
), /* @__PURE__ */ React26.createElement(Animated9.View, { style: bodyStyle }, /* @__PURE__ */ React26.createElement(
|
|
2116
2217
|
View,
|
|
2117
2218
|
{
|
|
2118
2219
|
style: styles20.content,
|
|
@@ -2212,23 +2313,38 @@ function Slider({
|
|
|
2212
2313
|
}
|
|
2213
2314
|
onValueChange?.(v);
|
|
2214
2315
|
};
|
|
2215
|
-
return /* @__PURE__ */ React26.createElement(
|
|
2216
|
-
|
|
2316
|
+
return /* @__PURE__ */ React26.createElement(
|
|
2317
|
+
View,
|
|
2217
2318
|
{
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2319
|
+
style: [styles21.wrapper, style],
|
|
2320
|
+
accessibilityRole: "adjustable",
|
|
2321
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
2322
|
+
accessibilityValue: {
|
|
2323
|
+
min: minimumValue,
|
|
2324
|
+
max: maximumValue,
|
|
2325
|
+
now: value,
|
|
2326
|
+
text: formatValue2(value)
|
|
2327
|
+
}
|
|
2328
|
+
},
|
|
2329
|
+
label || showValue ? /* @__PURE__ */ React26.createElement(View, { style: styles21.header }, label ? /* @__PURE__ */ React26.createElement(Text, { style: [styles21.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, showValue ? /* @__PURE__ */ React26.createElement(Text, { style: [styles21.valueText, { color: colors.foregroundMuted }], allowFontScaling: true }, formatValue2(value)) : null) : null,
|
|
2330
|
+
/* @__PURE__ */ React26.createElement(View, { style: disabled ? styles21.disabled : void 0 }, /* @__PURE__ */ React26.createElement(
|
|
2331
|
+
RNSlider,
|
|
2332
|
+
{
|
|
2333
|
+
value,
|
|
2334
|
+
minimumValue,
|
|
2335
|
+
maximumValue,
|
|
2336
|
+
step: step || 0,
|
|
2337
|
+
disabled,
|
|
2338
|
+
onValueChange: handleValueChange,
|
|
2339
|
+
onSlidingComplete,
|
|
2340
|
+
minimumTrackTintColor: colors.primary,
|
|
2341
|
+
maximumTrackTintColor: colors.surface,
|
|
2342
|
+
thumbTintColor: colors.primary,
|
|
2343
|
+
style: styles21.slider,
|
|
2344
|
+
accessibilityLabel
|
|
2345
|
+
}
|
|
2346
|
+
))
|
|
2347
|
+
);
|
|
2232
2348
|
}
|
|
2233
2349
|
var styles21 = StyleSheet.create({
|
|
2234
2350
|
wrapper: {
|
|
@@ -2304,13 +2420,16 @@ function Sheet({
|
|
|
2304
2420
|
}, [footer]);
|
|
2305
2421
|
const effectiveSubtitle = subtitle ?? description;
|
|
2306
2422
|
const showHeader = !!(title || effectiveSubtitle || showCloseButton);
|
|
2307
|
-
const headerNode = showHeader ? /* @__PURE__ */ React26.createElement(View, { style: styles22.header }, /* @__PURE__ */ React26.createElement(View, { style: styles22.headerRow }, title ? /* @__PURE__ */ React26.createElement(Text, { style: [styles22.title, { color: colors.foreground }], allowFontScaling: true }, title) : /* @__PURE__ */ React26.createElement(View, { style: { flex: 1 } }), showCloseButton ? /* @__PURE__ */ React26.createElement(
|
|
2423
|
+
const headerNode = showHeader ? /* @__PURE__ */ React26.createElement(View, { style: styles22.header, accessibilityRole: "header" }, /* @__PURE__ */ React26.createElement(View, { style: styles22.headerRow }, title ? /* @__PURE__ */ React26.createElement(Text, { style: [styles22.title, { color: colors.foreground }], allowFontScaling: true }, title) : /* @__PURE__ */ React26.createElement(View, { style: { flex: 1 } }), showCloseButton ? /* @__PURE__ */ React26.createElement(
|
|
2308
2424
|
TouchableOpacity,
|
|
2309
2425
|
{
|
|
2310
2426
|
onPress: onClose,
|
|
2311
2427
|
style: styles22.closeButton,
|
|
2312
2428
|
activeOpacity: 0.6,
|
|
2313
|
-
touchSoundDisabled: true
|
|
2429
|
+
touchSoundDisabled: true,
|
|
2430
|
+
accessibilityRole: "button",
|
|
2431
|
+
accessibilityLabel: "Close",
|
|
2432
|
+
hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
|
|
2314
2433
|
},
|
|
2315
2434
|
/* @__PURE__ */ React26.createElement(AntDesign$1, { name: "close", size: ms(18), color: colors.foregroundMuted })
|
|
2316
2435
|
) : null), effectiveSubtitle ? /* @__PURE__ */ React26.createElement(Text, { style: [styles22.subtitle, { color: colors.foregroundMuted }], allowFontScaling: true }, effectiveSubtitle) : null) : null;
|
|
@@ -2401,7 +2520,6 @@ var styles22 = StyleSheet.create({
|
|
|
2401
2520
|
var isIOS = Platform.OS === "ios";
|
|
2402
2521
|
var isAndroid2 = Platform.OS === "android";
|
|
2403
2522
|
var isWeb2 = Platform.OS === "web";
|
|
2404
|
-
var nativeDriver9 = Platform.OS !== "web";
|
|
2405
2523
|
function Select({
|
|
2406
2524
|
options,
|
|
2407
2525
|
value,
|
|
@@ -2410,21 +2528,18 @@ function Select({
|
|
|
2410
2528
|
label,
|
|
2411
2529
|
error,
|
|
2412
2530
|
disabled,
|
|
2413
|
-
style
|
|
2531
|
+
style,
|
|
2532
|
+
accessibilityLabel
|
|
2414
2533
|
}) {
|
|
2415
2534
|
const { colors } = useTheme();
|
|
2416
|
-
const
|
|
2535
|
+
const { animatedStyle, onPressIn, onPressOut } = usePressScale({
|
|
2536
|
+
pressScale: PRESS_SCALE.button,
|
|
2537
|
+
disabled
|
|
2538
|
+
});
|
|
2417
2539
|
const [pickerVisible, setPickerVisible] = useState(false);
|
|
2418
2540
|
const [pendingValue, setPendingValue] = useState(value);
|
|
2419
2541
|
const pickerRef = useRef(null);
|
|
2420
2542
|
const selected = options.find((o) => o.value === value);
|
|
2421
|
-
const handlePressIn = () => {
|
|
2422
|
-
if (disabled) return;
|
|
2423
|
-
Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver9, speed: 40, bounciness: 0 }).start();
|
|
2424
|
-
};
|
|
2425
|
-
const handlePressOut = () => {
|
|
2426
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver9, speed: 40, bounciness: 4 }).start();
|
|
2427
|
-
};
|
|
2428
2543
|
const handleOpen = () => {
|
|
2429
2544
|
if (disabled) return;
|
|
2430
2545
|
selectionAsync();
|
|
@@ -2445,7 +2560,7 @@ function Select({
|
|
|
2445
2560
|
}
|
|
2446
2561
|
setPickerVisible(false);
|
|
2447
2562
|
};
|
|
2448
|
-
return /* @__PURE__ */ React26.createElement(View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React26.createElement(Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React26.createElement(
|
|
2563
|
+
return /* @__PURE__ */ React26.createElement(View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React26.createElement(Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React26.createElement(Animated9.View, { style: [animatedStyle, { opacity: disabled ? 0.45 : 1 }] }, /* @__PURE__ */ React26.createElement(
|
|
2449
2564
|
TouchableOpacity,
|
|
2450
2565
|
{
|
|
2451
2566
|
style: [
|
|
@@ -2456,10 +2571,14 @@ function Select({
|
|
|
2456
2571
|
}
|
|
2457
2572
|
],
|
|
2458
2573
|
onPress: handleOpen,
|
|
2459
|
-
onPressIn
|
|
2460
|
-
onPressOut
|
|
2574
|
+
onPressIn,
|
|
2575
|
+
onPressOut,
|
|
2461
2576
|
activeOpacity: 1,
|
|
2462
|
-
touchSoundDisabled: true
|
|
2577
|
+
touchSoundDisabled: true,
|
|
2578
|
+
accessibilityRole: "combobox",
|
|
2579
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
2580
|
+
accessibilityValue: { text: selected?.label ?? placeholder },
|
|
2581
|
+
accessibilityState: { disabled: !!disabled, expanded: pickerVisible }
|
|
2463
2582
|
},
|
|
2464
2583
|
/* @__PURE__ */ React26.createElement(
|
|
2465
2584
|
Text,
|
|
@@ -2773,7 +2892,6 @@ var styles24 = StyleSheet.create({
|
|
|
2773
2892
|
textAlignVertical: "top"
|
|
2774
2893
|
}
|
|
2775
2894
|
});
|
|
2776
|
-
var nativeDriver10 = Platform.OS !== "web";
|
|
2777
2895
|
function ListItem({
|
|
2778
2896
|
leftRender,
|
|
2779
2897
|
rightRender,
|
|
@@ -2794,29 +2912,16 @@ function ListItem({
|
|
|
2794
2912
|
style,
|
|
2795
2913
|
titleStyle,
|
|
2796
2914
|
subtitleStyle,
|
|
2797
|
-
captionStyle
|
|
2915
|
+
captionStyle,
|
|
2916
|
+
accessibilityLabel
|
|
2798
2917
|
}) {
|
|
2799
2918
|
const { colors } = useTheme();
|
|
2800
|
-
const
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
stiffness: 350,
|
|
2807
|
-
damping: 28,
|
|
2808
|
-
mass: 0.9
|
|
2809
|
-
}).start();
|
|
2810
|
-
};
|
|
2811
|
-
const handlePressOut = () => {
|
|
2812
|
-
Animated.spring(scale2, {
|
|
2813
|
-
toValue: 1,
|
|
2814
|
-
useNativeDriver: nativeDriver10,
|
|
2815
|
-
stiffness: 220,
|
|
2816
|
-
damping: 20,
|
|
2817
|
-
mass: 0.9
|
|
2818
|
-
}).start();
|
|
2819
|
-
};
|
|
2919
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
2920
|
+
pressScale: PRESS_SCALE.row,
|
|
2921
|
+
pressInSpring: SPRINGS.surfacePressIn,
|
|
2922
|
+
pressOutSpring: SPRINGS.surfacePressOut,
|
|
2923
|
+
disabled: !onPress || disabled
|
|
2924
|
+
});
|
|
2820
2925
|
const handlePress = () => {
|
|
2821
2926
|
selectionAsync();
|
|
2822
2927
|
onPress?.();
|
|
@@ -2834,16 +2939,20 @@ function ListItem({
|
|
|
2834
2939
|
shadowRadius: 6,
|
|
2835
2940
|
elevation: 2
|
|
2836
2941
|
} : {};
|
|
2837
|
-
|
|
2942
|
+
const a11yLabel = accessibilityLabel ?? [title, subtitle, caption].filter(Boolean).join(". ");
|
|
2943
|
+
return /* @__PURE__ */ React26.createElement(Animated9.View, { style: [animatedStyle, disabled && styles25.disabled], ...hoverHandlers }, /* @__PURE__ */ React26.createElement(
|
|
2838
2944
|
TouchableOpacity,
|
|
2839
2945
|
{
|
|
2840
2946
|
style: [styles25.container, cardStyle, style],
|
|
2841
2947
|
onPress: onPress ? handlePress : void 0,
|
|
2842
|
-
onPressIn
|
|
2843
|
-
onPressOut
|
|
2948
|
+
onPressIn,
|
|
2949
|
+
onPressOut,
|
|
2844
2950
|
disabled,
|
|
2845
2951
|
activeOpacity: 1,
|
|
2846
|
-
touchSoundDisabled: true
|
|
2952
|
+
touchSoundDisabled: true,
|
|
2953
|
+
accessibilityRole: onPress ? "button" : void 0,
|
|
2954
|
+
accessibilityLabel: onPress ? a11yLabel : void 0,
|
|
2955
|
+
accessibilityState: onPress ? { disabled: !!disabled } : void 0
|
|
2847
2956
|
},
|
|
2848
2957
|
effectiveLeft ? /* @__PURE__ */ React26.createElement(View, { style: styles25.leftContainer }, effectiveLeft) : null,
|
|
2849
2958
|
/* @__PURE__ */ React26.createElement(View, { style: styles25.content }, /* @__PURE__ */ React26.createElement(
|
|
@@ -2937,9 +3046,6 @@ var styles25 = StyleSheet.create({
|
|
|
2937
3046
|
fontFamily: "Poppins-Regular",
|
|
2938
3047
|
fontSize: ms(14)
|
|
2939
3048
|
},
|
|
2940
|
-
chevron: {
|
|
2941
|
-
marginLeft: s(4)
|
|
2942
|
-
},
|
|
2943
3049
|
separator: {
|
|
2944
3050
|
height: StyleSheet.hairlineWidth,
|
|
2945
3051
|
marginRight: 0
|
|
@@ -2948,7 +3054,6 @@ var styles25 = StyleSheet.create({
|
|
|
2948
3054
|
opacity: 0.45
|
|
2949
3055
|
}
|
|
2950
3056
|
});
|
|
2951
|
-
var nativeDriver11 = Platform.OS !== "web";
|
|
2952
3057
|
function MenuItem({
|
|
2953
3058
|
label,
|
|
2954
3059
|
subtitle,
|
|
@@ -2962,29 +3067,16 @@ function MenuItem({
|
|
|
2962
3067
|
variant = "plain",
|
|
2963
3068
|
showSeparator = false,
|
|
2964
3069
|
style,
|
|
2965
|
-
labelStyle
|
|
3070
|
+
labelStyle,
|
|
3071
|
+
accessibilityLabel
|
|
2966
3072
|
}) {
|
|
2967
3073
|
const { colors } = useTheme();
|
|
2968
|
-
const
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
stiffness: 350,
|
|
2975
|
-
damping: 28,
|
|
2976
|
-
mass: 0.9
|
|
2977
|
-
}).start();
|
|
2978
|
-
};
|
|
2979
|
-
const handlePressOut = () => {
|
|
2980
|
-
Animated.spring(scale2, {
|
|
2981
|
-
toValue: 1,
|
|
2982
|
-
useNativeDriver: nativeDriver11,
|
|
2983
|
-
stiffness: 220,
|
|
2984
|
-
damping: 20,
|
|
2985
|
-
mass: 0.9
|
|
2986
|
-
}).start();
|
|
2987
|
-
};
|
|
3074
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3075
|
+
pressScale: PRESS_SCALE.row,
|
|
3076
|
+
pressInSpring: SPRINGS.surfacePressIn,
|
|
3077
|
+
pressOutSpring: SPRINGS.surfacePressOut,
|
|
3078
|
+
disabled
|
|
3079
|
+
});
|
|
2988
3080
|
const handlePress = () => {
|
|
2989
3081
|
selectionAsync();
|
|
2990
3082
|
onPress();
|
|
@@ -3001,16 +3093,20 @@ function MenuItem({
|
|
|
3001
3093
|
shadowRadius: 6,
|
|
3002
3094
|
elevation: 2
|
|
3003
3095
|
} : {};
|
|
3004
|
-
|
|
3096
|
+
const a11yLabel = accessibilityLabel ?? (subtitle ? `${label}. ${subtitle}` : label);
|
|
3097
|
+
return /* @__PURE__ */ React26.createElement(Animated9.View, { style: [animatedStyle, disabled && styles26.disabled], ...hoverHandlers }, /* @__PURE__ */ React26.createElement(
|
|
3005
3098
|
TouchableOpacity,
|
|
3006
3099
|
{
|
|
3007
3100
|
style: [styles26.container, cardStyle, style],
|
|
3008
3101
|
onPress: handlePress,
|
|
3009
|
-
onPressIn
|
|
3010
|
-
onPressOut
|
|
3102
|
+
onPressIn,
|
|
3103
|
+
onPressOut,
|
|
3011
3104
|
disabled,
|
|
3012
3105
|
activeOpacity: 1,
|
|
3013
|
-
touchSoundDisabled: true
|
|
3106
|
+
touchSoundDisabled: true,
|
|
3107
|
+
accessibilityRole: "button",
|
|
3108
|
+
accessibilityLabel: a11yLabel,
|
|
3109
|
+
accessibilityState: { disabled }
|
|
3014
3110
|
},
|
|
3015
3111
|
resolvedIcon ? /* @__PURE__ */ React26.createElement(View, { style: styles26.iconContainer }, resolvedIcon) : null,
|
|
3016
3112
|
/* @__PURE__ */ React26.createElement(View, { style: styles26.labelContainer }, /* @__PURE__ */ React26.createElement(
|
|
@@ -3095,62 +3191,37 @@ var styles26 = StyleSheet.create({
|
|
|
3095
3191
|
opacity: 0.45
|
|
3096
3192
|
}
|
|
3097
3193
|
});
|
|
3098
|
-
|
|
3099
|
-
function Chip({ label, selected = false, onPress, icon, iconName, style }) {
|
|
3194
|
+
function Chip({ label, selected = false, onPress, icon, iconName, style, accessibilityLabel }) {
|
|
3100
3195
|
const { colors } = useTheme();
|
|
3101
|
-
const
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
Animated.spring(scale2, {
|
|
3113
|
-
toValue: 0.95,
|
|
3114
|
-
useNativeDriver: nativeDriver12,
|
|
3115
|
-
speed: 40,
|
|
3116
|
-
bounciness: 0
|
|
3117
|
-
}).start();
|
|
3118
|
-
};
|
|
3119
|
-
const handlePressOut = () => {
|
|
3120
|
-
Animated.spring(scale2, {
|
|
3121
|
-
toValue: 1,
|
|
3122
|
-
useNativeDriver: nativeDriver12,
|
|
3123
|
-
speed: 40,
|
|
3124
|
-
bounciness: 4
|
|
3125
|
-
}).start();
|
|
3126
|
-
};
|
|
3196
|
+
const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3197
|
+
pressScale: PRESS_SCALE.chip
|
|
3198
|
+
});
|
|
3199
|
+
const colorProgress = useColorTransition(selected);
|
|
3200
|
+
const surfaceStyle = useAnimatedStyle(() => ({
|
|
3201
|
+
backgroundColor: interpolateColor(colorProgress.value, [0, 1], [colors.surface, colors.primary]),
|
|
3202
|
+
borderColor: interpolateColor(colorProgress.value, [0, 1], [colors.border, colors.primary])
|
|
3203
|
+
}));
|
|
3204
|
+
const textStyle = useAnimatedStyle(() => ({
|
|
3205
|
+
color: interpolateColor(colorProgress.value, [0, 1], [colors.foreground, colors.primaryForeground])
|
|
3206
|
+
}));
|
|
3127
3207
|
const handlePress = () => {
|
|
3128
3208
|
selectionAsync();
|
|
3129
3209
|
onPress?.();
|
|
3130
3210
|
};
|
|
3131
|
-
const backgroundColor = pressAnim.interpolate({
|
|
3132
|
-
inputRange: [0, 1],
|
|
3133
|
-
outputRange: [colors.surface, colors.primary]
|
|
3134
|
-
});
|
|
3135
|
-
const textColor = pressAnim.interpolate({
|
|
3136
|
-
inputRange: [0, 1],
|
|
3137
|
-
outputRange: [colors.foreground, colors.primaryForeground]
|
|
3138
|
-
});
|
|
3139
|
-
const borderColor = pressAnim.interpolate({
|
|
3140
|
-
inputRange: [0, 1],
|
|
3141
|
-
outputRange: [colors.border, colors.primary]
|
|
3142
|
-
});
|
|
3143
3211
|
const resolvedIcon = iconName ? renderIcon(iconName, ms(13), selected ? colors.primaryForeground : colors.foreground) : icon;
|
|
3144
|
-
return /* @__PURE__ */ React26.createElement(
|
|
3212
|
+
return /* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles27.wrapper, scaleStyle, style], ...hoverHandlers }, /* @__PURE__ */ React26.createElement(
|
|
3145
3213
|
TouchableOpacity,
|
|
3146
3214
|
{
|
|
3147
3215
|
onPress: handlePress,
|
|
3148
|
-
onPressIn
|
|
3149
|
-
onPressOut
|
|
3216
|
+
onPressIn,
|
|
3217
|
+
onPressOut,
|
|
3150
3218
|
activeOpacity: 1,
|
|
3151
|
-
touchSoundDisabled: true
|
|
3219
|
+
touchSoundDisabled: true,
|
|
3220
|
+
accessibilityRole: "button",
|
|
3221
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
3222
|
+
accessibilityState: { selected }
|
|
3152
3223
|
},
|
|
3153
|
-
/* @__PURE__ */ React26.createElement(
|
|
3224
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles27.chip, surfaceStyle] }, resolvedIcon ? /* @__PURE__ */ React26.createElement(View, { style: styles27.chipIcon }, resolvedIcon) : null, /* @__PURE__ */ React26.createElement(Animated9.Text, { style: [styles27.label, textStyle], allowFontScaling: true }, label))
|
|
3154
3225
|
));
|
|
3155
3226
|
}
|
|
3156
3227
|
function ChipGroup({ options, value, onValueChange, multiSelect = false, style }) {
|
|
@@ -3161,12 +3232,7 @@ function ChipGroup({ options, value, onValueChange, multiSelect = false, style }
|
|
|
3161
3232
|
}
|
|
3162
3233
|
const currentArray = Array.isArray(value) ? value : value ? [value] : [];
|
|
3163
3234
|
const isSelected2 = currentArray.includes(optionValue);
|
|
3164
|
-
|
|
3165
|
-
if (isSelected2) {
|
|
3166
|
-
newArray = currentArray.filter((v) => v !== optionValue);
|
|
3167
|
-
} else {
|
|
3168
|
-
newArray = [...currentArray, optionValue];
|
|
3169
|
-
}
|
|
3235
|
+
const newArray = isSelected2 ? currentArray.filter((v) => v !== optionValue) : [...currentArray, optionValue];
|
|
3170
3236
|
onValueChange?.(newArray);
|
|
3171
3237
|
};
|
|
3172
3238
|
const isSelected = (optionValue) => {
|
|
@@ -3380,22 +3446,36 @@ function MonthPicker({ value, onChange, locale = "en", formatLabel, style }) {
|
|
|
3380
3446
|
onChange({ month: value.month + 1, year: value.year });
|
|
3381
3447
|
}
|
|
3382
3448
|
};
|
|
3383
|
-
return /* @__PURE__ */ React26.createElement(View, { style: [styles30.container, style] }, /* @__PURE__ */ React26.createElement(
|
|
3449
|
+
return /* @__PURE__ */ React26.createElement(View, { style: [styles30.container, style], accessibilityRole: "adjustable", accessibilityLabel: getLabel() }, /* @__PURE__ */ React26.createElement(
|
|
3384
3450
|
TouchableOpacity,
|
|
3385
3451
|
{
|
|
3386
3452
|
style: styles30.arrow,
|
|
3387
3453
|
onPress: handlePrev,
|
|
3388
3454
|
activeOpacity: 0.6,
|
|
3389
|
-
touchSoundDisabled: true
|
|
3455
|
+
touchSoundDisabled: true,
|
|
3456
|
+
accessibilityRole: "button",
|
|
3457
|
+
accessibilityLabel: "Previous month",
|
|
3458
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
|
|
3390
3459
|
},
|
|
3391
3460
|
/* @__PURE__ */ React26.createElement(Entypo$1, { name: "chevron-left", size: 22, color: colors.foreground })
|
|
3392
|
-
), /* @__PURE__ */ React26.createElement(
|
|
3461
|
+
), /* @__PURE__ */ React26.createElement(
|
|
3462
|
+
Text,
|
|
3463
|
+
{
|
|
3464
|
+
style: [styles30.label, { color: colors.foreground }],
|
|
3465
|
+
allowFontScaling: true,
|
|
3466
|
+
accessibilityLiveRegion: "polite"
|
|
3467
|
+
},
|
|
3468
|
+
getLabel()
|
|
3469
|
+
), /* @__PURE__ */ React26.createElement(
|
|
3393
3470
|
TouchableOpacity,
|
|
3394
3471
|
{
|
|
3395
3472
|
style: styles30.arrow,
|
|
3396
3473
|
onPress: handleNext,
|
|
3397
3474
|
activeOpacity: 0.6,
|
|
3398
|
-
touchSoundDisabled: true
|
|
3475
|
+
touchSoundDisabled: true,
|
|
3476
|
+
accessibilityRole: "button",
|
|
3477
|
+
accessibilityLabel: "Next month",
|
|
3478
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
|
|
3399
3479
|
},
|
|
3400
3480
|
/* @__PURE__ */ React26.createElement(Entypo$1, { name: "chevron-right", size: 22, color: colors.foreground })
|
|
3401
3481
|
));
|
|
@@ -3420,18 +3500,6 @@ var styles30 = StyleSheet.create({
|
|
|
3420
3500
|
minWidth: s(160)
|
|
3421
3501
|
}
|
|
3422
3502
|
});
|
|
3423
|
-
function useHover() {
|
|
3424
|
-
const [hovered, setHovered] = useState(false);
|
|
3425
|
-
const onMouseEnter = useCallback(() => setHovered(true), []);
|
|
3426
|
-
const onMouseLeave = useCallback(() => setHovered(false), []);
|
|
3427
|
-
if (Platform.OS !== "web") {
|
|
3428
|
-
return { hovered: false, hoverHandlers: {} };
|
|
3429
|
-
}
|
|
3430
|
-
return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
|
|
3431
|
-
}
|
|
3432
|
-
|
|
3433
|
-
// src/components/MediaCard/MediaCard.tsx
|
|
3434
|
-
var nativeDriver13 = Platform.OS !== "web";
|
|
3435
3503
|
var aspectRatioMap = {
|
|
3436
3504
|
"1:1": 1,
|
|
3437
3505
|
"4:3": 3 / 4,
|
|
@@ -3453,19 +3521,17 @@ function MediaCard({
|
|
|
3453
3521
|
onPress,
|
|
3454
3522
|
style,
|
|
3455
3523
|
imageStyle,
|
|
3456
|
-
footer
|
|
3524
|
+
footer,
|
|
3525
|
+
accessibilityLabel
|
|
3457
3526
|
}) {
|
|
3458
3527
|
const { colors } = useTheme();
|
|
3459
|
-
const scale2 = useRef(new Animated.Value(1)).current;
|
|
3460
3528
|
const { hovered, hoverHandlers } = useHover();
|
|
3461
|
-
const
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver13, speed: 40, bounciness: 4 }).start();
|
|
3468
|
-
};
|
|
3529
|
+
const { animatedStyle, onPressIn, onPressOut } = usePressScale({
|
|
3530
|
+
pressScale: PRESS_SCALE.card,
|
|
3531
|
+
pressInSpring: SPRINGS.surfacePressIn,
|
|
3532
|
+
pressOutSpring: SPRINGS.surfacePressOut,
|
|
3533
|
+
disabled: !onPress
|
|
3534
|
+
});
|
|
3469
3535
|
const handlePress = () => {
|
|
3470
3536
|
if (!onPress) return;
|
|
3471
3537
|
impactLight();
|
|
@@ -3473,6 +3539,7 @@ function MediaCard({
|
|
|
3473
3539
|
};
|
|
3474
3540
|
const ratio = aspectRatioMap[aspectRatio];
|
|
3475
3541
|
const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
|
|
3542
|
+
const a11yLabel = accessibilityLabel ?? [title, subtitle].filter(Boolean).join(". ");
|
|
3476
3543
|
const cardContent = /* @__PURE__ */ React26.createElement(
|
|
3477
3544
|
View,
|
|
3478
3545
|
{
|
|
@@ -3499,21 +3566,26 @@ function MediaCard({
|
|
|
3499
3566
|
onActionPress?.();
|
|
3500
3567
|
},
|
|
3501
3568
|
activeOpacity: 0.8,
|
|
3502
|
-
touchSoundDisabled: true
|
|
3569
|
+
touchSoundDisabled: true,
|
|
3570
|
+
accessibilityRole: "button",
|
|
3571
|
+
accessibilityLabel: actionIconName ?? "action",
|
|
3572
|
+
accessibilityState: { selected: actionActive }
|
|
3503
3573
|
},
|
|
3504
3574
|
resolvedActionIcon
|
|
3505
3575
|
)),
|
|
3506
3576
|
(title || subtitle || caption || footer) && /* @__PURE__ */ React26.createElement(View, { style: styles31.meta }, title ? /* @__PURE__ */ React26.createElement(Text, { style: [styles31.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React26.createElement(Text, { style: [styles31.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React26.createElement(Text, { style: [styles31.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
|
|
3507
3577
|
);
|
|
3508
3578
|
if (onPress) {
|
|
3509
|
-
return /* @__PURE__ */ React26.createElement(
|
|
3579
|
+
return /* @__PURE__ */ React26.createElement(Animated9.View, { style: animatedStyle }, /* @__PURE__ */ React26.createElement(
|
|
3510
3580
|
TouchableOpacity,
|
|
3511
3581
|
{
|
|
3512
3582
|
onPress: handlePress,
|
|
3513
|
-
onPressIn
|
|
3514
|
-
onPressOut
|
|
3583
|
+
onPressIn,
|
|
3584
|
+
onPressOut,
|
|
3515
3585
|
activeOpacity: 1,
|
|
3516
|
-
touchSoundDisabled: true
|
|
3586
|
+
touchSoundDisabled: true,
|
|
3587
|
+
accessibilityRole: "button",
|
|
3588
|
+
accessibilityLabel: a11yLabel
|
|
3517
3589
|
},
|
|
3518
3590
|
cardContent
|
|
3519
3591
|
));
|
|
@@ -3523,12 +3595,10 @@ function MediaCard({
|
|
|
3523
3595
|
var styles31 = StyleSheet.create({
|
|
3524
3596
|
card: {
|
|
3525
3597
|
borderRadius: RADIUS.md,
|
|
3526
|
-
// 14px — Airbnb property card spec
|
|
3527
3598
|
overflow: "hidden",
|
|
3528
3599
|
backgroundColor: "transparent"
|
|
3529
3600
|
},
|
|
3530
3601
|
cardHovered: {
|
|
3531
|
-
// Web hover: lift shadow
|
|
3532
3602
|
...SHADOWS.md
|
|
3533
3603
|
},
|
|
3534
3604
|
imageContainer: {
|
|
@@ -3579,43 +3649,38 @@ var styles31 = StyleSheet.create({
|
|
|
3579
3649
|
lineHeight: mvs(16)
|
|
3580
3650
|
}
|
|
3581
3651
|
});
|
|
3582
|
-
var nativeDriver14 = Platform.OS !== "web";
|
|
3583
3652
|
function CategoryChip({
|
|
3584
3653
|
item,
|
|
3585
3654
|
selected,
|
|
3586
3655
|
onPress
|
|
3587
3656
|
}) {
|
|
3588
3657
|
const { colors } = useTheme();
|
|
3589
|
-
const
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
const
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
const
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3658
|
+
const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3659
|
+
pressScale: PRESS_SCALE.chip
|
|
3660
|
+
});
|
|
3661
|
+
const progress = useColorTransition(selected);
|
|
3662
|
+
const surfaceStyle = useAnimatedStyle(() => ({
|
|
3663
|
+
backgroundColor: interpolateColor(progress.value, [0, 1], [colors.surface, colors.primary]),
|
|
3664
|
+
borderColor: interpolateColor(progress.value, [0, 1], [colors.border, colors.primary])
|
|
3665
|
+
}));
|
|
3666
|
+
const textColorStyle = useAnimatedStyle(() => ({
|
|
3667
|
+
color: interpolateColor(progress.value, [0, 1], [colors.foregroundSubtle, colors.primaryForeground])
|
|
3668
|
+
}));
|
|
3669
|
+
const iconColor = selected ? colors.primaryForeground : colors.foregroundSubtle;
|
|
3670
|
+
const resolvedIcon = typeof item.icon === "string" ? renderIcon(item.icon, 16, iconColor) : item.icon ?? null;
|
|
3671
|
+
return /* @__PURE__ */ React26.createElement(Animated9.View, { style: scaleStyle, ...hoverHandlers }, /* @__PURE__ */ React26.createElement(
|
|
3601
3672
|
TouchableOpacity,
|
|
3602
3673
|
{
|
|
3603
|
-
style: [
|
|
3604
|
-
styles32.chip,
|
|
3605
|
-
{
|
|
3606
|
-
backgroundColor: bgColor,
|
|
3607
|
-
borderColor
|
|
3608
|
-
}
|
|
3609
|
-
],
|
|
3610
3674
|
onPress,
|
|
3611
|
-
onPressIn
|
|
3612
|
-
onPressOut
|
|
3675
|
+
onPressIn,
|
|
3676
|
+
onPressOut,
|
|
3613
3677
|
activeOpacity: 1,
|
|
3614
|
-
touchSoundDisabled: true
|
|
3678
|
+
touchSoundDisabled: true,
|
|
3679
|
+
accessibilityRole: "button",
|
|
3680
|
+
accessibilityLabel: item.label,
|
|
3681
|
+
accessibilityState: { selected }
|
|
3615
3682
|
},
|
|
3616
|
-
resolvedIcon && /* @__PURE__ */ React26.createElement(View, { style: styles32.chipIcon }, resolvedIcon),
|
|
3617
|
-
/* @__PURE__ */ React26.createElement(Text, { style: [styles32.chipLabel, { color: textColor }], allowFontScaling: true }, item.label),
|
|
3618
|
-
item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React26.createElement(View, { style: [styles32.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React26.createElement(Text, { style: [styles32.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99)))
|
|
3683
|
+
/* @__PURE__ */ React26.createElement(Animated9.View, { style: [styles32.chip, surfaceStyle] }, resolvedIcon && /* @__PURE__ */ React26.createElement(View, { style: styles32.chipIcon }, resolvedIcon), /* @__PURE__ */ React26.createElement(Animated9.Text, { style: [styles32.chipLabel, textColorStyle], allowFontScaling: true }, item.label), item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React26.createElement(View, { style: [styles32.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React26.createElement(Text, { style: [styles32.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99))))
|
|
3619
3684
|
));
|
|
3620
3685
|
}
|
|
3621
3686
|
function CategoryStrip({
|
|
@@ -3624,7 +3689,8 @@ function CategoryStrip({
|
|
|
3624
3689
|
onValueChange,
|
|
3625
3690
|
multiSelect = false,
|
|
3626
3691
|
style,
|
|
3627
|
-
itemStyle
|
|
3692
|
+
itemStyle,
|
|
3693
|
+
accessibilityLabel
|
|
3628
3694
|
}) {
|
|
3629
3695
|
const selected = Array.isArray(value) ? value : value ? [value] : [];
|
|
3630
3696
|
const handlePress = (v) => {
|
|
@@ -3643,7 +3709,9 @@ function CategoryStrip({
|
|
|
3643
3709
|
horizontal: true,
|
|
3644
3710
|
showsHorizontalScrollIndicator: false,
|
|
3645
3711
|
contentContainerStyle: [styles32.container, style],
|
|
3646
|
-
style: styles32.scroll
|
|
3712
|
+
style: styles32.scroll,
|
|
3713
|
+
accessibilityRole: multiSelect ? void 0 : "radiogroup",
|
|
3714
|
+
accessibilityLabel
|
|
3647
3715
|
},
|
|
3648
3716
|
categories.map((cat) => /* @__PURE__ */ React26.createElement(View, { key: cat.value, style: itemStyle }, /* @__PURE__ */ React26.createElement(
|
|
3649
3717
|
CategoryChip,
|
|
@@ -3696,62 +3764,45 @@ var styles32 = StyleSheet.create({
|
|
|
3696
3764
|
lineHeight: 14
|
|
3697
3765
|
}
|
|
3698
3766
|
});
|
|
3699
|
-
var nativeDriver15 = Platform.OS !== "web";
|
|
3700
3767
|
function Pressable2({
|
|
3701
3768
|
children,
|
|
3702
3769
|
onPress,
|
|
3703
|
-
pressScale =
|
|
3704
|
-
bounciness = 4,
|
|
3770
|
+
pressScale = PRESS_SCALE.card,
|
|
3705
3771
|
haptics = true,
|
|
3706
3772
|
style,
|
|
3707
3773
|
disabled,
|
|
3708
3774
|
hoverScale = 1.02,
|
|
3709
3775
|
...touchableProps
|
|
3710
3776
|
}) {
|
|
3711
|
-
const
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
speed: 40,
|
|
3719
|
-
bounciness: 0
|
|
3720
|
-
}).start();
|
|
3721
|
-
};
|
|
3722
|
-
const handlePressOut = () => {
|
|
3723
|
-
if (disabled) return;
|
|
3724
|
-
Animated.spring(scale2, {
|
|
3725
|
-
toValue: 1,
|
|
3726
|
-
useNativeDriver: nativeDriver15,
|
|
3727
|
-
speed: 40,
|
|
3728
|
-
bounciness
|
|
3729
|
-
}).start();
|
|
3730
|
-
};
|
|
3777
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3778
|
+
pressScale,
|
|
3779
|
+
hoverScale,
|
|
3780
|
+
pressInSpring: SPRINGS.surfacePressIn,
|
|
3781
|
+
pressOutSpring: SPRINGS.surfacePressOut,
|
|
3782
|
+
disabled
|
|
3783
|
+
});
|
|
3731
3784
|
const handlePress = () => {
|
|
3732
3785
|
if (disabled || !onPress) return;
|
|
3733
3786
|
if (haptics) impactLight();
|
|
3734
3787
|
onPress();
|
|
3735
3788
|
};
|
|
3736
|
-
const hoverScaleValue = hovered && hoverScale !== 1 ? hoverScale : 1;
|
|
3737
3789
|
return /* @__PURE__ */ React26.createElement(
|
|
3738
|
-
|
|
3790
|
+
Animated9.View,
|
|
3739
3791
|
{
|
|
3740
|
-
style: [
|
|
3741
|
-
{ transform: [{ scale: Animated.multiply(scale2, hoverScaleValue) }] },
|
|
3742
|
-
style
|
|
3743
|
-
],
|
|
3792
|
+
style: [animatedStyle, style],
|
|
3744
3793
|
...Platform.OS === "web" ? hoverHandlers : {}
|
|
3745
3794
|
},
|
|
3746
3795
|
/* @__PURE__ */ React26.createElement(
|
|
3747
3796
|
TouchableOpacity,
|
|
3748
3797
|
{
|
|
3749
3798
|
onPress: handlePress,
|
|
3750
|
-
onPressIn
|
|
3751
|
-
onPressOut
|
|
3799
|
+
onPressIn,
|
|
3800
|
+
onPressOut,
|
|
3752
3801
|
activeOpacity: 1,
|
|
3753
3802
|
disabled,
|
|
3754
3803
|
touchSoundDisabled: true,
|
|
3804
|
+
accessibilityRole: "button",
|
|
3805
|
+
accessibilityState: { disabled: !!disabled },
|
|
3755
3806
|
...touchableProps
|
|
3756
3807
|
},
|
|
3757
3808
|
children
|