orn-ui 0.2.6 → 0.2.8

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.
Files changed (146) hide show
  1. package/AGENTS.md +372 -0
  2. package/README.md +46 -15
  3. package/lib/commonjs/atoms/Gradient.js +111 -0
  4. package/lib/commonjs/atoms/Gradient.js.map +1 -0
  5. package/lib/commonjs/atoms/index.js +7 -0
  6. package/lib/commonjs/atoms/index.js.map +1 -1
  7. package/lib/commonjs/organisms/Slides.js +406 -0
  8. package/lib/commonjs/organisms/Slides.js.map +1 -0
  9. package/lib/commonjs/organisms/index.js +7 -0
  10. package/lib/commonjs/organisms/index.js.map +1 -1
  11. package/lib/commonjs/organisms/useSlides.js +186 -0
  12. package/lib/commonjs/organisms/useSlides.js.map +1 -0
  13. package/lib/module/atoms/Gradient.js +106 -0
  14. package/lib/module/atoms/Gradient.js.map +1 -0
  15. package/lib/module/atoms/index.js +1 -0
  16. package/lib/module/atoms/index.js.map +1 -1
  17. package/lib/module/organisms/Slides.js +401 -0
  18. package/lib/module/organisms/Slides.js.map +1 -0
  19. package/lib/module/organisms/index.js +1 -0
  20. package/lib/module/organisms/index.js.map +1 -1
  21. package/lib/module/organisms/useSlides.js +182 -0
  22. package/lib/module/organisms/useSlides.js.map +1 -0
  23. package/lib/typescript/atoms/Badge.d.ts +1 -1
  24. package/lib/typescript/atoms/Badge.d.ts.map +1 -1
  25. package/lib/typescript/atoms/Gradient.d.ts +37 -0
  26. package/lib/typescript/atoms/Gradient.d.ts.map +1 -0
  27. package/lib/typescript/atoms/Image.d.ts +6 -6
  28. package/lib/typescript/atoms/Image.d.ts.map +1 -1
  29. package/lib/typescript/atoms/Input.d.ts +1 -1
  30. package/lib/typescript/atoms/Input.d.ts.map +1 -1
  31. package/lib/typescript/atoms/PressableScale.d.ts +1 -1
  32. package/lib/typescript/atoms/PressableScale.d.ts.map +1 -1
  33. package/lib/typescript/atoms/Skeleton.d.ts +5 -5
  34. package/lib/typescript/atoms/Skeleton.d.ts.map +1 -1
  35. package/lib/typescript/atoms/Spinner.d.ts +4 -4
  36. package/lib/typescript/atoms/Spinner.d.ts.map +1 -1
  37. package/lib/typescript/atoms/Transition.d.ts +10 -10
  38. package/lib/typescript/atoms/Transition.d.ts.map +1 -1
  39. package/lib/typescript/atoms/index.d.ts +2 -0
  40. package/lib/typescript/atoms/index.d.ts.map +1 -1
  41. package/lib/typescript/molecules/AvatarHeader.d.ts +2 -2
  42. package/lib/typescript/molecules/AvatarHeader.d.ts.map +1 -1
  43. package/lib/typescript/molecules/FormActions.d.ts +1 -1
  44. package/lib/typescript/molecules/FormActions.d.ts.map +1 -1
  45. package/lib/typescript/molecules/OptionCard.d.ts +2 -2
  46. package/lib/typescript/molecules/OptionCard.d.ts.map +1 -1
  47. package/lib/typescript/molecules/Stepper.d.ts +8 -8
  48. package/lib/typescript/molecules/Stepper.d.ts.map +1 -1
  49. package/lib/typescript/molecules/Steps.d.ts +3 -3
  50. package/lib/typescript/molecules/Steps.d.ts.map +1 -1
  51. package/lib/typescript/molecules/SymmetricGrid.d.ts +4 -4
  52. package/lib/typescript/molecules/SymmetricGrid.d.ts.map +1 -1
  53. package/lib/typescript/organisms/BottomSheet.d.ts +8 -8
  54. package/lib/typescript/organisms/BottomSheet.d.ts.map +1 -1
  55. package/lib/typescript/organisms/DateField.d.ts +10 -10
  56. package/lib/typescript/organisms/DateField.d.ts.map +1 -1
  57. package/lib/typescript/organisms/DatePicker.d.ts +10 -10
  58. package/lib/typescript/organisms/DatePicker.d.ts.map +1 -1
  59. package/lib/typescript/organisms/List.d.ts +6 -6
  60. package/lib/typescript/organisms/List.d.ts.map +1 -1
  61. package/lib/typescript/organisms/NavigationBar.d.ts +2 -2
  62. package/lib/typescript/organisms/NavigationBar.d.ts.map +1 -1
  63. package/lib/typescript/organisms/ReorderableList.d.ts +7 -7
  64. package/lib/typescript/organisms/ReorderableList.d.ts.map +1 -1
  65. package/lib/typescript/organisms/Screen.d.ts +6 -6
  66. package/lib/typescript/organisms/SearchList.d.ts +8 -8
  67. package/lib/typescript/organisms/SearchList.d.ts.map +1 -1
  68. package/lib/typescript/organisms/Select.d.ts +2 -2
  69. package/lib/typescript/organisms/Select.d.ts.map +1 -1
  70. package/lib/typescript/organisms/Slides.d.ts +69 -0
  71. package/lib/typescript/organisms/Slides.d.ts.map +1 -0
  72. package/lib/typescript/organisms/Toast.d.ts +2 -2
  73. package/lib/typescript/organisms/Toast.d.ts.map +1 -1
  74. package/lib/typescript/organisms/ToastProvider.d.ts +2 -2
  75. package/lib/typescript/organisms/ToastProvider.d.ts.map +1 -1
  76. package/lib/typescript/organisms/Wizard.d.ts +7 -7
  77. package/lib/typescript/organisms/Wizard.d.ts.map +1 -1
  78. package/lib/typescript/organisms/index.d.ts +2 -0
  79. package/lib/typescript/organisms/index.d.ts.map +1 -1
  80. package/lib/typescript/organisms/useSlides.d.ts +52 -0
  81. package/lib/typescript/organisms/useSlides.d.ts.map +1 -0
  82. package/lib/typescript/theme/UIProvider.d.ts +9 -9
  83. package/lib/typescript/theme/UIProvider.d.ts.map +1 -1
  84. package/llms.txt +34 -0
  85. package/package.json +34 -6
  86. package/registry/avatar-header.json +1 -1
  87. package/registry/badge.json +1 -1
  88. package/registry/bottom-sheet.json +1 -1
  89. package/registry/core.json +1 -1
  90. package/registry/date-field.json +1 -1
  91. package/registry/date-picker.json +1 -1
  92. package/registry/form-actions.json +1 -1
  93. package/registry/gradient.json +18 -0
  94. package/registry/image.json +1 -1
  95. package/registry/index.json +52 -26
  96. package/registry/input.json +1 -1
  97. package/registry/list.json +1 -1
  98. package/registry/manifest.json +14 -0
  99. package/registry/navigation-bar.json +1 -1
  100. package/registry/option-card.json +1 -1
  101. package/registry/pressable-scale.json +1 -1
  102. package/registry/reorderable-list.json +1 -1
  103. package/registry/screen.json +1 -1
  104. package/registry/search-list.json +1 -1
  105. package/registry/select.json +1 -1
  106. package/registry/skeleton.json +1 -1
  107. package/registry/slides.json +24 -0
  108. package/registry/spinner.json +1 -1
  109. package/registry/stepper.json +1 -1
  110. package/registry/steps.json +1 -1
  111. package/registry/symmetric-grid.json +1 -1
  112. package/registry/toast-provider.json +1 -1
  113. package/registry/toast.json +1 -1
  114. package/registry/transition.json +1 -1
  115. package/registry/wizard.json +1 -1
  116. package/src/atoms/Badge.tsx +1 -1
  117. package/src/atoms/Gradient.tsx +99 -0
  118. package/src/atoms/Image.tsx +6 -6
  119. package/src/atoms/Input.tsx +1 -1
  120. package/src/atoms/PressableScale.tsx +1 -1
  121. package/src/atoms/Skeleton.tsx +5 -5
  122. package/src/atoms/Spinner.tsx +4 -4
  123. package/src/atoms/Transition.tsx +10 -10
  124. package/src/atoms/index.ts +2 -0
  125. package/src/molecules/AvatarHeader.tsx +2 -2
  126. package/src/molecules/FormActions.tsx +1 -1
  127. package/src/molecules/OptionCard.tsx +2 -2
  128. package/src/molecules/Stepper.tsx +8 -8
  129. package/src/molecules/Steps.tsx +3 -3
  130. package/src/molecules/SymmetricGrid.tsx +4 -4
  131. package/src/organisms/BottomSheet.tsx +8 -8
  132. package/src/organisms/DateField.tsx +10 -10
  133. package/src/organisms/DatePicker.tsx +10 -10
  134. package/src/organisms/List.tsx +6 -6
  135. package/src/organisms/NavigationBar.tsx +2 -2
  136. package/src/organisms/ReorderableList.tsx +7 -7
  137. package/src/organisms/Screen.tsx +6 -6
  138. package/src/organisms/SearchList.tsx +8 -8
  139. package/src/organisms/Select.tsx +2 -2
  140. package/src/organisms/Slides.tsx +413 -0
  141. package/src/organisms/Toast.tsx +2 -2
  142. package/src/organisms/ToastProvider.tsx +2 -2
  143. package/src/organisms/Wizard.tsx +7 -7
  144. package/src/organisms/index.ts +8 -0
  145. package/src/organisms/useSlides.ts +220 -0
  146. package/src/theme/UIProvider.tsx +9 -9
@@ -0,0 +1,99 @@
1
+ import React, { memo, useMemo } from 'react';
2
+ import { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';
3
+
4
+ export type GradientDirection = 'vertical' | 'horizontal' | 'diagonal' | 'diagonal-reverse';
5
+
6
+ export interface GradientProps {
7
+ /** Paradas del degradado. Uno solo pinta plano; ninguno no pinta nada. */
8
+ colors: string[];
9
+ /**
10
+ * 'vertical' va de arriba a abajo, 'horizontal' de izquierda a derecha,
11
+ * 'diagonal' de arriba-izquierda a abajo-derecha y 'diagonal-reverse' de
12
+ * arriba-derecha a abajo-izquierda.
13
+ * @default 'vertical'
14
+ */
15
+ direction?: GradientDirection;
16
+ /**
17
+ * Bandas por tramo (un tramo = un par de colores consecutivos). Más bandas
18
+ * = transición más suave y más vistas en el árbol.
19
+ * @default 24
20
+ */
21
+ steps?: number;
22
+ /** Contenido por encima del degradado. */
23
+ children?: React.ReactNode;
24
+ style?: StyleProp<ViewStyle>;
25
+ testID?: string;
26
+ }
27
+
28
+ const DEFAULT_STEPS = 24;
29
+
30
+ const styles = StyleSheet.create({
31
+ // Recorta el plano rotado de las diagonales y el degradado al borderRadius.
32
+ root: { overflow: 'hidden' },
33
+ segment: { flex: 1 },
34
+ band: { flex: 1 },
35
+ // Plano √2 centrado: rotado 45° cubre las esquinas sin medir el contenedor.
36
+ diagonalPlane: { position: 'absolute', top: '-21%', left: '-21%', width: '142%', height: '142%' },
37
+ });
38
+
39
+ /**
40
+ * Gradient
41
+ * Degradado lineal sin dependencias: React Native no trae uno en el rango
42
+ * soportado (Expo SDK 54–57) y `experimental_backgroundImage` no está en toda
43
+ * esa ventana, así que se compone con bandas.
44
+ *
45
+ * Cada tramo pinta el color inicial y encima N bandas del final con opacidad
46
+ * de 0 a 1. El compositor mezcla alpha linealmente: el resultado es la
47
+ * interpolación sRGB entre paradas sin parsear el color, y por eso vale
48
+ * cualquier formato que acepte RN (hex, `rgba()`, nombre).
49
+ */
50
+ export const Gradient = memo(
51
+ ({ colors, direction = 'vertical', steps = DEFAULT_STEPS, children, style, testID }: GradientProps) => {
52
+ const isRow = direction === 'horizontal';
53
+ const isDiagonal = direction === 'diagonal' || direction === 'diagonal-reverse';
54
+ // rotate positivo gira en horario (Y crece hacia abajo): -45° manda el eje
55
+ // del degradado hacia abajo-derecha.
56
+ const rotate = direction === 'diagonal' ? '-45deg' : '45deg';
57
+ const bandCount = Math.max(2, Math.floor(steps));
58
+
59
+ const painted = useMemo(() => {
60
+ if (colors.length === 0) return null;
61
+ if (colors.length === 1) {
62
+ return <View style={[StyleSheet.absoluteFill, { backgroundColor: colors[0] }]} />;
63
+ }
64
+
65
+ const segments = colors.slice(0, -1).map((from, index) => {
66
+ const to = colors[index + 1] as string;
67
+ return (
68
+ <View
69
+ key={`${from}-${to}-${index}`}
70
+ style={[styles.segment, { backgroundColor: from, flexDirection: isRow ? 'row' : 'column' }]}
71
+ >
72
+ {Array.from({ length: bandCount }, (_, band) => (
73
+ <View key={band} style={[styles.band, { backgroundColor: to, opacity: band / (bandCount - 1) }]} />
74
+ ))}
75
+ </View>
76
+ );
77
+ });
78
+
79
+ const stack = (
80
+ <View style={[StyleSheet.absoluteFill, { flexDirection: isRow ? 'row' : 'column' }]}>{segments}</View>
81
+ );
82
+
83
+ if (!isDiagonal) return stack;
84
+ return <View style={[styles.diagonalPlane, { transform: [{ rotate }] }]}>{segments}</View>;
85
+ }, [colors, isRow, isDiagonal, rotate, bandCount]);
86
+
87
+ return (
88
+ <View testID={testID} style={[styles.root, style]}>
89
+ {/* pointerEvents va en el pintado, no en la raíz: el degradado no debe
90
+ robarle los toques a lo que el consumidor ponga encima. */}
91
+ <View style={StyleSheet.absoluteFill} pointerEvents="none">
92
+ {painted}
93
+ </View>
94
+ {children}
95
+ </View>
96
+ );
97
+ }
98
+ );
99
+ Gradient.displayName = 'Gradient';
@@ -20,16 +20,16 @@ export interface ImageProps {
20
20
  height?: number;
21
21
  /** @default 'cover' */
22
22
  resizeMode?: ImageResizeMode;
23
- /** Radio de las esquinas, mismo patrón que Avatar/Card. @default 0 */
23
+ /** Corner radius, same pattern as Avatar/Card. @default 0 */
24
24
  radius?: number;
25
- /** Qué mostrar mientras carga. `false` para no mostrar nada. @default true (spinner chico) */
25
+ /** What to show while loading. `false` to show nothing. @default true (small spinner) */
26
26
  loading?: React.ReactNode | boolean;
27
- /** Qué mostrar si la carga falla. @default un placeholder gris, sin contenido */
27
+ /** What to show if loading fails. @default a gray placeholder, no content */
28
28
  fallback?: React.ReactNode;
29
29
  /**
30
- * 'high' dispara Image.prefetch() al montar, antes de que <Image> arranque
31
- * su propio ciclo de carga — pensado para la imagen above-the-fold de una
32
- * pantalla (la primera que el usuario ve). Sin costo si ya está en caché.
30
+ * 'high' triggers Image.prefetch() on mount, before <Image> starts
31
+ * its own load cycle — meant for the above-the-fold image of a
32
+ * screen (the first one the user sees). No cost if it's already cached.
33
33
  * @default 'normal'
34
34
  */
35
35
  priority?: 'low' | 'normal' | 'high';
@@ -17,7 +17,7 @@ import type { IconName } from '../icons/types';
17
17
 
18
18
  export interface InputProps extends Omit<TextInputProps, 'style'> {
19
19
  label?: string;
20
- /** Muestra un asterisco junto al label. Puramente visual, no valida nada. */
20
+ /** Shows an asterisk next to the label. Purely visual, doesn't validate anything. */
21
21
  required?: boolean;
22
22
  error?: string;
23
23
  containerStyle?: StyleProp<ViewStyle>;
@@ -9,7 +9,7 @@ import {
9
9
  } from 'react-native';
10
10
 
11
11
  export interface PressableScaleProps extends Omit<PressableProps, 'style'> {
12
- /** Escala objetivo al presionar. @default 0.96 */
12
+ /** Target scale when pressed. @default 0.96 */
13
13
  scaleTo?: number;
14
14
  style?: StyleProp<ViewStyle>;
15
15
  children: React.ReactNode;
@@ -13,17 +13,17 @@ import { useTheme } from '../theme/UIProvider';
13
13
  export type SkeletonVariant = 'rect' | 'text' | 'circle';
14
14
 
15
15
  export interface SkeletonProps {
16
- /** @default '100%' ('circle' lo usa también como diámetro) */
16
+ /** @default '100%' ('circle' also uses this as the diameter) */
17
17
  width?: DimensionValue;
18
- /** @default 16 ('text' usa el alto de línea; 'circle', el ancho) */
18
+ /** @default 16 ('text' uses the line height; 'circle', the width) */
19
19
  height?: DimensionValue;
20
20
  /** @default 'rect' */
21
21
  variant?: SkeletonVariant;
22
- /** Override del radius del theme. */
22
+ /** Override of the theme's radius. */
23
23
  radius?: number;
24
- /** Líneas apiladas, sólo para variant="text". @default 1 */
24
+ /** Stacked lines, only for variant="text". @default 1 */
25
25
  lines?: number;
26
- /** Ancho de la última línea, para que el párrafo no termine en bloque. @default '60%' */
26
+ /** Width of the last line, so the paragraph doesn't end as a solid block. @default '60%' */
27
27
  lastLineWidth?: DimensionValue;
28
28
  /** @default true */
29
29
  animated?: boolean;
@@ -9,15 +9,15 @@ export interface SpinnerProps {
9
9
  size?: 'small' | 'large';
10
10
  color?: string;
11
11
  text?: string;
12
- /** @default true. En false, no ocupa flex:1 (útil inline, dentro de un botón/fila). */
12
+ /** @default true. When false, doesn't take up flex:1 (useful inline, inside a button/row). */
13
13
  fullscreen?: boolean;
14
14
  /**
15
- * 'native' usa el ActivityIndicator del sistema; 'dots' y 'ring' son
16
- * indicadores propios, iguales en iOS y Android.
15
+ * 'native' uses the system's ActivityIndicator; 'dots' and 'ring' are
16
+ * custom indicators, identical on iOS and Android.
17
17
  * @default 'native'
18
18
  */
19
19
  variant?: SpinnerVariant;
20
- /** Indicador totalmente propio. Gana sobre `variant`. */
20
+ /** Fully custom indicator. Takes precedence over `variant`. */
21
21
  indicator?: React.ReactNode;
22
22
  testID?: string;
23
23
  }
@@ -13,25 +13,25 @@ export type TransitionPreset =
13
13
 
14
14
  export interface TransitionProps {
15
15
  children: React.ReactNode;
16
- /** Entra en true, sale (y desmonta) en false. @default true */
16
+ /** Enters when true, exits (and unmounts) when false. @default true */
17
17
  visible?: boolean;
18
- /** Uno o varios: 'fade scale' combina opacidad y escala. @default 'fade' */
18
+ /** One or more: 'fade scale' combines opacity and scale. @default 'fade' */
19
19
  preset?: TransitionPreset | TransitionPreset[];
20
- /** ms del timing. @default tokens.duration.base */
20
+ /** Timing duration in ms. @default tokens.duration.base */
21
21
  duration?: number;
22
- /** ms antes de arrancar. Un índice por delay escalona una lista. @default 0 */
22
+ /** ms before starting. A per-index delay staggers a list. @default 0 */
23
23
  delay?: number;
24
- /** Píxeles que recorren los presets de slide. @default 24 */
24
+ /** Pixels traveled by the slide presets. @default 24 */
25
25
  distance?: number;
26
- /** Spring en vez de timing (implícito en 'pop'). */
26
+ /** Spring instead of timing (implicit in 'pop'). */
27
27
  spring?: boolean;
28
- /** Anima también el primer render. En false arranca ya presente. @default true */
28
+ /** Also animates the first render. When false it starts already present. @default true */
29
29
  appear?: boolean;
30
- /** Deja el nodo montado al salir, sólo lo esconde. @default false */
30
+ /** Keeps the node mounted on exit, only hides it. @default false */
31
31
  keepMounted?: boolean;
32
32
  /**
33
- * Progreso 0→1 manejado desde afuera. Con esto el Transition sólo interpola:
34
- * quien lo pasa decide cuándo y cómo avanza (un PanResponder, por ejemplo).
33
+ * 0→1 progress driven from outside. With this, Transition only interpolates:
34
+ * whoever passes it decides when and how it advances (a PanResponder, for example).
35
35
  */
36
36
  value?: Animated.Value;
37
37
  onEntered?: () => void;
@@ -14,6 +14,8 @@ export { Card } from './Card';
14
14
  export type { CardProps } from './Card';
15
15
  export { Divider } from './Divider';
16
16
  export type { DividerProps } from './Divider';
17
+ export { Gradient } from './Gradient';
18
+ export type { GradientProps, GradientDirection } from './Gradient';
17
19
  export { Avatar } from './Avatar';
18
20
  export type { AvatarProps } from './Avatar';
19
21
  export { Image, prefetchImage } from './Image';
@@ -6,10 +6,10 @@ import { Icon } from '../icons/Icon';
6
6
  import type { IconName } from '../icons/types';
7
7
 
8
8
  export interface AvatarHeaderProps {
9
- /** Ícono a mostrar dentro del círculo. Si se omite, se usan `initials`. */
9
+ /** Icon to show inside the circle. If omitted, `initials` is used instead. */
10
10
  iconName?: IconName;
11
11
  iconColor?: string;
12
- /** Texto corto (ej. 2 letras) mostrado si no se pasa `iconName`. */
12
+ /** Short text (e.g. 2 letters) shown when `iconName` isn't provided. */
13
13
  initials?: string;
14
14
  title: string;
15
15
  subtitle?: React.ReactNode;
@@ -5,7 +5,7 @@ import type { IconName } from '../icons/types';
5
5
  import { useLabels } from '../theme/UIProvider';
6
6
 
7
7
  export interface FormActionsProps {
8
- /** Si se omite, solo se muestra el botón secundario. */
8
+ /** If omitted, only the secondary button is shown. */
9
9
  primaryLabel?: string;
10
10
  onPrimaryPress?: () => void;
11
11
  primaryDisabled?: boolean;
@@ -8,13 +8,13 @@ import type { IconName } from '../icons/types';
8
8
 
9
9
  export interface OptionCardProps {
10
10
  label: string;
11
- /** Línea secundaria: el detalle que decide la elección ("llega en 3 días"). */
11
+ /** Secondary line: the detail that decides the choice ("arrives in 3 days"). */
12
12
  description?: string;
13
13
  iconName?: IconName;
14
14
  isSelected: boolean;
15
15
  onPress: () => void;
16
16
  disabled?: boolean;
17
- /** 'vertical': ícono arriba, texto abajo centrado. 'horizontal': en fila. @default 'horizontal' */
17
+ /** 'vertical': icon on top, text centered below. 'horizontal': in a row. @default 'horizontal' */
18
18
  layout?: 'vertical' | 'horizontal';
19
19
  style?: StyleProp<ViewStyle>;
20
20
  testID?: string;
@@ -11,23 +11,23 @@ export interface StepperProps {
11
11
  onChangeText: (text: string) => void;
12
12
  onIncrement: () => void;
13
13
  onDecrement: () => void;
14
- /** Escala del control: alto, botones, ícono y tipografía. @default 'md' */
14
+ /** Scale of the control: height, buttons, icon and typography. @default 'md' */
15
15
  size?: StepperSize;
16
- /** Ocupa todo el ancho disponible y el input se lleva el sobrante. @default false */
16
+ /** Takes up all available width and the input absorbs the extra space. @default false */
17
17
  block?: boolean;
18
18
  /**
19
- * En false el valor sólo se cambia con los botones: el teclado no se abre y
20
- * el campo pierde el fondo que lo anuncia como editable. @default true
19
+ * When false the value can only be changed with the buttons: the keyboard doesn't open and
20
+ * the field loses the background that marks it as editable. @default true
21
21
  */
22
22
  editable?: boolean;
23
23
  /**
24
- * Mínimo permitido. Deshabilita "-" al alcanzarlo y acota lo tipeado al
25
- * salir del campo. Los negativos se aceptan sólo si `min` es negativo.
24
+ * Minimum allowed value. Disables "-" when reached and clamps the typed value on
25
+ * blur. Negative values are only accepted if `min` is negative.
26
26
  */
27
27
  min?: number;
28
- /** Máximo permitido. Deshabilita "+" al alcanzarlo y acota lo tipeado. */
28
+ /** Maximum allowed value. Disables "+" when reached and clamps the typed value. */
29
29
  max?: number;
30
- /** Acepta un separador decimal, normalizando la coma a punto. @default false */
30
+ /** Accepts a decimal separator, normalizing comma to dot. @default false */
31
31
  allowDecimals?: boolean;
32
32
  style?: StyleProp<ViewStyle>;
33
33
  incrementAccessibilityLabel?: string;
@@ -13,16 +13,16 @@ export type StepStatus = 'completed' | 'current' | 'pending';
13
13
 
14
14
  export interface StepsProps {
15
15
  steps: StepItem[];
16
- /** Índice del paso actual (0-based). Los anteriores quedan 'completed'. */
16
+ /** Index of the current step (0-based). Earlier steps become 'completed'. */
17
17
  current: number;
18
18
  /** @default 'horizontal' */
19
19
  orientation?: 'horizontal' | 'vertical';
20
20
  /**
21
- * Qué muestra el círculo de un paso ya completado: un check, o su número.
21
+ * What the circle of an already-completed step shows: a check, or its number.
22
22
  * @default 'check'
23
23
  */
24
24
  completedIndicator?: 'check' | 'number';
25
- /** Si se pasa, cada paso es tocable y reporta su índice. */
25
+ /** If provided, each step is tappable and reports its index. */
26
26
  onStepPress?: (index: number) => void;
27
27
  style?: StyleProp<ViewStyle>;
28
28
  }
@@ -6,13 +6,13 @@ export interface SymmetricGridProps<T> {
6
6
  data: T[];
7
7
  renderItem: (item: T, index: number) => React.ReactElement;
8
8
  keyExtractor: (item: T, index: number) => string;
9
- /** Columnas por fila. @default 2 */
9
+ /** Columns per row. @default 2 */
10
10
  columns?: number;
11
- /** Separación entre celdas, en ambos ejes. @default theme.tokens.spacing.md */
11
+ /** Spacing between cells, on both axes. @default theme.tokens.spacing.md */
12
12
  gap?: number;
13
13
  /**
14
- * Última fila incompleta: centrada (simétrica) en vez de pegada a la
15
- * izquierda con un hueco a la derecha. @default true
14
+ * Incomplete last row: centered (symmetric) instead of stuck to the
15
+ * left with a gap on the right. @default true
16
16
  */
17
17
  balanceLastRow?: boolean;
18
18
  style?: StyleProp<ViewStyle>;
@@ -27,21 +27,21 @@ export interface BottomSheetProps {
27
27
  visible: boolean;
28
28
  onClose: () => void;
29
29
  children: React.ReactNode;
30
- /** Con título aparece el header, con su botón de cerrar. */
30
+ /** With a title, the header appears, with its close button. */
31
31
  title?: string;
32
- /** Acciones de la hoja. Dónde vive lo decide `footerPlacement`. */
32
+ /** Sheet actions. Where they live is decided by `footerPlacement`. */
33
33
  footer?: React.ReactNode;
34
34
  /**
35
- * 'fixed' lo ancla al pie de la hoja; 'scroll' lo deja al final del
36
- * contenido; 'hide-with-keyboard' lo esconde mientras se escribe, que en un
37
- * formulario largo le devuelve esa franja al campo enfocado. @default 'fixed'
35
+ * 'fixed' anchors it to the bottom of the sheet; 'scroll' leaves it at the
36
+ * end of the content; 'hide-with-keyboard' hides it while typing, which in a
37
+ * long form gives that strip back to the focused field. @default 'fixed'
38
38
  */
39
39
  footerPlacement?: FooterPlacement;
40
- /** El contenido scrollea cuando no entra. @default true */
40
+ /** The content scrolls when it doesn't fit. @default true */
41
41
  scrollable?: boolean;
42
- /** Arrastrar la hoja hacia abajo la cierra. @default true */
42
+ /** Dragging the sheet down closes it. @default true */
43
43
  draggable?: boolean;
44
- /** Fracción de la pantalla (0-1) o píxeles. @default 0.9 */
44
+ /** Fraction of the screen (0-1) or pixels. @default 0.9 */
45
45
  maxHeight?: number;
46
46
  closeAccessibilityLabel?: string;
47
47
  containerStyle?: ViewStyle;
@@ -11,31 +11,31 @@ export interface DateFieldProps
11
11
  label?: string;
12
12
  required?: boolean;
13
13
  /**
14
- * 'single' elige una fecha; 'range' elige un intervalo con dos toques.
14
+ * 'single' picks one date; 'range' picks an interval with two taps.
15
15
  * @default 'single'
16
16
  */
17
17
  mode?: 'single' | 'range';
18
- /** Fecha elegida en mode="single". */
18
+ /** Selected date in mode="single". */
19
19
  value?: Date;
20
- /** Se llama en mode="single". */
20
+ /** Called in mode="single". */
21
21
  onChange?: (date: Date) => void;
22
- /** Rango elegido en mode="range". */
22
+ /** Selected range in mode="range". */
23
23
  range?: DateRange;
24
- /** Se llama en mode="range", tanto al fijar el inicio como al cerrar el rango. */
24
+ /** Called in mode="range", both when setting the start and when closing the range. */
25
25
  onRangeChange?: (range: DateRange) => void;
26
26
  placeholder?: string;
27
27
  error?: string;
28
28
  disabled?: boolean;
29
- /** Formatea la fecha en el campo. @default "Month D, YYYY" */
29
+ /** Formats the date in the field. @default "Month D, YYYY" */
30
30
  format?: (date: Date) => string;
31
- /** Título del modal del calendario. @default el `selectDate` de `useLabels()` */
31
+ /** Title of the calendar modal. @default the `selectDate` from `useLabels()` */
32
32
  modalTitle?: string;
33
33
  /**
34
- * Si se pasa, el modal muestra un botón que borra la selección y cierra.
35
- * Sin esto no hay botón: el "Clear" anterior sólo cerraba, sin limpiar nada.
34
+ * If provided, the modal shows a button that clears the selection and closes.
35
+ * Without this there's no button: the previous "Clear" only closed, without clearing anything.
36
36
  */
37
37
  onClear?: () => void;
38
- /** Texto de ese botón. @default el `clear` de `useLabels()` */
38
+ /** Text for that button. @default the `clear` from `useLabels()` */
39
39
  clearLabel?: string;
40
40
  containerStyle?: StyleProp<ViewStyle>;
41
41
  testID?: string;
@@ -20,29 +20,29 @@ export interface DateRange {
20
20
 
21
21
  export interface DatePickerProps {
22
22
  /**
23
- * 'single' elige una fecha; 'range' elige un intervalo con dos toques.
23
+ * 'single' picks one date; 'range' picks an interval with two taps.
24
24
  * @default 'single'
25
25
  */
26
26
  mode?: 'single' | 'range';
27
- /** Fecha elegida en mode="single". */
27
+ /** Selected date in mode="single". */
28
28
  value?: Date;
29
- /** Se llama en mode="single". */
29
+ /** Called in mode="single". */
30
30
  onChange?: (date: Date) => void;
31
- /** Rango elegido en mode="range". */
31
+ /** Selected range in mode="range". */
32
32
  range?: DateRange;
33
- /** Se llama en mode="range", tanto al fijar el inicio como al cerrar el rango. */
33
+ /** Called in mode="range", both when setting the start and when closing the range. */
34
34
  onRangeChange?: (range: DateRange) => void;
35
35
  minDate?: Date;
36
36
  maxDate?: Date;
37
- /** Mes mostrado al abrir si no hay `value`. @default hoy */
37
+ /** Month shown on open if there's no `value`. @default today */
38
38
  defaultMonth?: Date;
39
- /** Nombres de los meses. @default los de `useLabels()` */
39
+ /** Month names. @default those from `useLabels()` */
40
40
  monthNames?: string[];
41
- /** Iniciales de los días, índice 0 = domingo. @default las de `useLabels()` */
41
+ /** Day initials, index 0 = Sunday. @default those from `useLabels()` */
42
42
  weekdayNames?: string[];
43
- /** 0 = domingo, 1 = lunes. @default 0 */
43
+ /** 0 = Sunday, 1 = Monday. @default 0 */
44
44
  firstDayOfWeek?: 0 | 1;
45
- /** Avisa qué mes quedó a la vista al navegar con las flechas. */
45
+ /** Reports which month became visible when navigating with the arrows. */
46
46
  onVisibleMonthChange?: (month: Date) => void;
47
47
  style?: StyleProp<ViewStyle>;
48
48
  testID?: string;
@@ -12,19 +12,19 @@ export interface ListProps<T> {
12
12
  keyExtractor: (item: T, index: number) => string;
13
13
  renderItem: FlatListProps<T>['renderItem'];
14
14
 
15
- /** Carga inicial: mientras sea true y no haya datos, se muestran placeholders. */
15
+ /** Initial load: while true and there's no data, placeholders are shown. */
16
16
  isLoading: boolean;
17
- /** Recarga con datos ya en pantalla (pull-to-refresh). @default false */
17
+ /** Reload with data already on screen (pull-to-refresh). @default false */
18
18
  isRefreshing?: boolean;
19
19
  isLoadingMore?: boolean;
20
- /** Controlado por el consumidor: mientras es false, se muestra un spinner de pantalla completa. @default true */
20
+ /** Controlled by the consumer: while false, a fullscreen spinner is shown. @default true */
21
21
  isReady?: boolean;
22
22
  loadingText?: string;
23
23
  loadingMoreText?: string;
24
24
 
25
- /** Filas fantasma de la carga inicial. @default 6 */
25
+ /** Ghost rows for the initial load. @default 6 */
26
26
  skeletonCount?: number;
27
- /** Placeholder propio, para que calce con la forma real del ítem. */
27
+ /** Custom placeholder, to match the real shape of the item. */
28
28
  renderSkeletonItem?: () => React.ReactElement;
29
29
 
30
30
  onEndReached?: () => void;
@@ -41,7 +41,7 @@ export interface ListProps<T> {
41
41
  contentContainerStyle?: ViewStyle;
42
42
  containerStyle?: ViewStyle;
43
43
 
44
- /** Componente de lista a usar (FlashList, etc). @default FlatList */
44
+ /** List component to use (FlashList, etc). @default FlatList */
45
45
  ListComponent?: React.ComponentType<any>;
46
46
  listProps?: Record<string, unknown>;
47
47
  }
@@ -26,11 +26,11 @@ export interface NavigationBarProps {
26
26
  items: NavigationBarItem[];
27
27
  activeKey: string;
28
28
  onChange: (key: string) => void;
29
- /** Borde de la pantalla donde vive la barra. @default 'bottom' */
29
+ /** Screen edge where the bar lives. @default 'bottom' */
30
30
  position?: 'bottom' | 'top';
31
31
  /** @default true */
32
32
  showLabels?: boolean;
33
- /** Suma el inset de safe area del borde donde vive la barra. @default true */
33
+ /** Adds the safe area inset for the edge where the bar lives. @default true */
34
34
  safeArea?: boolean;
35
35
  style?: StyleProp<ViewStyle>;
36
36
  testID?: string;
@@ -5,19 +5,19 @@ import { createStyles } from '../theme/createStyles';
5
5
  export interface ReorderableListProps<T> {
6
6
  data: T[];
7
7
  keyExtractor: (item: T, index: number) => string;
8
- /** Alto fijo de cada fila: necesario para calcular el índice destino sin medir layout async. */
8
+ /** Fixed height of each row: needed to calculate the target index without measuring layout async. */
9
9
  itemHeight: number;
10
10
  renderItem: (item: T, index: number, dragging: boolean) => React.ReactElement;
11
- /** Se llama al soltar, con el arreglo ya reordenado. No muta `data`. */
11
+ /** Called on release, with the array already reordered. Does not mutate `data`. */
12
12
  onReorder: (data: T[]) => void;
13
13
  /**
14
- * Empieza el arrastre de la fila `index`. Úsalo para apagar el scroll del
15
- * contenedor (`scrollEnabled={false}`) mientras dura: en iOS el
16
- * `UIScrollView` padre cancela los toques del contenido apenas su gesto
17
- * vertical arranca, y sin eso el arrastre muere a los pocos píxeles.
14
+ * Starts dragging row `index`. Use it to turn off the container's scroll
15
+ * (`scrollEnabled={false}`) while it lasts: on iOS the parent
16
+ * `UIScrollView` cancels touches on the content as soon as its
17
+ * vertical gesture starts, and without this the drag dies within a few pixels.
18
18
  */
19
19
  onDragStart?: (index: number) => void;
20
- /** Termina el arrastre — soltando o por cancelación. Siempre corre si corrió `onDragStart`. */
20
+ /** Ends the drag — on release or cancellation. Always runs if `onDragStart` ran. */
21
21
  onDragEnd?: () => void;
22
22
  disabled?: boolean;
23
23
  style?: StyleProp<ViewStyle>;
@@ -10,14 +10,14 @@ export interface ScreenProps {
10
10
  style?: ViewStyle;
11
11
  scrollable?: boolean;
12
12
  contentContainerStyle?: ViewStyle;
13
- /** Qué insets de safe area aplicar. @default ['top', 'bottom'] */
13
+ /** Which safe area insets to apply. @default ['top', 'bottom'] */
14
14
  edges?: ScreenEdge[];
15
15
  /**
16
- * Compensa el teclado: en iOS con scroll lo hace el propio ScrollView, en el
17
- * resto de los casos con un KeyboardAvoidingView. Ponelo en false cuando
18
- * el contenido ya trae su propio scroller que maneja el teclado (Wizard,
19
- * List, SearchList): las dos compensaciones se suman y el campo enfocado
20
- * termina empujado fuera de la pantalla.
16
+ * Compensates for the keyboard: on iOS with scroll the ScrollView itself does it, in
17
+ * other cases a KeyboardAvoidingView does. Set to false when
18
+ * the content already brings its own scroller that handles the keyboard (Wizard,
19
+ * List, SearchList): the two compensations add up and the focused field
20
+ * ends up pushed off screen.
21
21
  * @default true
22
22
  */
23
23
  keyboardAvoiding?: boolean;