react-native-varia 0.2.3 → 0.2.4

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 (35) hide show
  1. package/bin/cli.js +24 -34
  2. package/lib/components/Accordion.tsx +113 -0
  3. package/lib/components/Button.tsx +10 -1
  4. package/lib/components/CircleProgress.tsx +30 -21
  5. package/lib/components/Divider.tsx +18 -15
  6. package/lib/components/Drawer.tsx +5 -48
  7. package/lib/components/Field.tsx +24 -39
  8. package/lib/components/GradientBackground.tsx +25 -7
  9. package/lib/components/GradientText.tsx +38 -11
  10. package/lib/components/IconWrapper.tsx +20 -14
  11. package/lib/components/Input.tsx +106 -25
  12. package/lib/components/NumberInput.tsx +54 -11
  13. package/lib/components/OldSlider.tsx +327 -0
  14. package/lib/components/RadioGroup.tsx +55 -17
  15. package/lib/components/ReText.tsx +1 -1
  16. package/lib/components/Select.tsx +58 -22
  17. package/lib/components/Slider.tsx +176 -115
  18. package/lib/components/Slideshow.tsx +65 -63
  19. package/lib/components/SlidingDrawer.tsx +20 -21
  20. package/lib/components/Spinner.tsx +6 -2
  21. package/lib/components/Toast.tsx +89 -0
  22. package/lib/components/context/Field.tsx +27 -0
  23. package/lib/theme/Button.recipe.tsx +11 -1
  24. package/lib/theme/CircleProgress.recipe.tsx +3 -3
  25. package/lib/theme/Field.recipe.tsx +17 -2
  26. package/lib/theme/Input.recipe.tsx +12 -3
  27. package/lib/theme/NumberInput.recipe.tsx +8 -3
  28. package/lib/theme/RadioGroup.recipe.tsx +7 -1
  29. package/lib/theme/Select.recipe.tsx +7 -7
  30. package/lib/theme/Slider.recipe.tsx +366 -22
  31. package/lib/theme/Slideshow.recipe.tsx +1 -1
  32. package/lib/theme/SlidingDrawer.recipe.tsx +58 -4
  33. package/lib/theme/Toast.recipe.tsx +71 -0
  34. package/package.json +1 -1
  35. package/lib/theme/Button.recipe-old.tsx +0 -67
package/bin/cli.js CHANGED
@@ -1,11 +1,10 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  const { program } = require("commander");
4
4
  const inquirer = require("inquirer");
5
5
  const path = require("path");
6
6
  const fs = require("fs-extra");
7
7
 
8
- // 🔹 Dependencias entre componentes
9
8
  const COMPONENT_DEPENDENCIES = {
10
9
  Button: ["Spinner", "IconWrapper"],
11
10
  Field: ["Text"],
@@ -19,9 +18,18 @@ const ICON_DEPENDENCIES = {
19
18
  NumberInput: ["Plus", "Minus"],
20
19
  };
21
20
 
22
- /**
23
- * Obtiene todas las dependencias de un componente de forma recursiva.
24
- */
21
+ const CONTEXT_DEPENDENCIES = {
22
+ Field: true
23
+ };
24
+
25
+ function copyContextComponentIfNeeded(component, destComponents, overwrite = true) {
26
+ if (!CONTEXT_DEPENDENCIES[component]) return;
27
+
28
+ const contextSrc = path.join(COMPONENTS_DIR, "context", `${component}.tsx`);
29
+ const contextDest = path.join(process.cwd(), destComponents, "context", `${component}.tsx`);
30
+ copyFile(contextSrc, contextDest, `Context de "${component}"`, overwrite);
31
+ }
32
+
25
33
  function resolveDependencies(component, seen = new Set()) {
26
34
  if (seen.has(component)) return [];
27
35
  seen.add(component);
@@ -36,21 +44,14 @@ function resolveDependencies(component, seen = new Set()) {
36
44
  return [...new Set(allDeps)];
37
45
  }
38
46
 
39
- // Carpetas base
40
47
  const COMPONENTS_DIR = path.join(__dirname, "../lib/components");
41
48
  const THEME_DIR = path.join(__dirname, "../lib/theme");
42
49
 
43
- /**
44
- * Obtiene la lista de todos los componentes disponibles en la librería.
45
- */
46
50
  function getAvailableComponents() {
47
51
  if (!fs.existsSync(COMPONENTS_DIR)) return [];
48
52
  return fs.readdirSync(COMPONENTS_DIR).map((name) => path.parse(name).name);
49
53
  }
50
54
 
51
- /**
52
- * Copia un archivo desde origen a destino.
53
- */
54
55
  function copyFile(srcPath, destPath, label, overwrite = true) {
55
56
  if (!fs.existsSync(srcPath)) {
56
57
  console.warn(`⚠️ ${label} no encontrado: ${srcPath}`);
@@ -73,9 +74,6 @@ function copyFile(srcPath, destPath, label, overwrite = true) {
73
74
  }
74
75
  }
75
76
 
76
- /**
77
- * Copia un componente y su recipe.
78
- */
79
77
  function copyComponentAndRecipe(component, destComponents, destTheme, overwrite = true) {
80
78
  const componentSrc = path.join(COMPONENTS_DIR, `${component}.tsx`);
81
79
  const componentDest = path.join(process.cwd(), destComponents, `${component}.tsx`);
@@ -86,9 +84,6 @@ function copyComponentAndRecipe(component, destComponents, destTheme, overwrite
86
84
  copyFile(recipeSrc, recipeDest, `Recipe de "${component}"`, overwrite);
87
85
  }
88
86
 
89
- /**
90
- * Pregunta si se desea sobrescribir componentes existentes.
91
- */
92
87
  async function confirmOverwrite(existingComponents) {
93
88
  const { overwrite } = await inquirer.prompt([
94
89
  {
@@ -119,12 +114,10 @@ program
119
114
  const patternsDest = path.join(process.cwd(), "src/patterns");
120
115
 
121
116
  try {
122
- // Copiar varia
123
117
  fs.ensureDirSync(path.dirname(variaDest));
124
118
  fs.copySync(variaSrc, variaDest, { overwrite: true });
125
119
  console.log(`✅ Carpeta "varia" copiada a ${variaDest}`);
126
120
 
127
- // Copiar patterns
128
121
  fs.ensureDirSync(path.dirname(patternsDest));
129
122
  fs.copySync(patternsSrc, patternsDest, { overwrite: true });
130
123
  console.log(`✅ Carpeta "patterns" copiada a ${patternsDest}`);
@@ -233,9 +226,8 @@ program
233
226
  (c) => c.charAt(0).toUpperCase() + c.slice(1)
234
227
  );
235
228
 
236
- // 🔹 Obtener dependencias totales
237
229
  const allComponents = new Set();
238
- const componentToDeps = {}; // para saber qué depende de qué
230
+ const componentToDeps = {};
239
231
  for (const c of componentsCapitalized) {
240
232
  const deps = resolveDependencies(c);
241
233
  componentToDeps[c] = deps;
@@ -245,7 +237,6 @@ program
245
237
 
246
238
  const allComponentsArray = Array.from(allComponents);
247
239
 
248
- // 🔹 Validar existencia
249
240
  const notFound = allComponentsArray.filter((c) => !available.includes(c));
250
241
  if (notFound.length > 0) {
251
242
  console.error(`❌ Los siguientes componentes no existen: ${notFound.join(", ")}`);
@@ -254,12 +245,18 @@ program
254
245
  process.exit(1);
255
246
  }
256
247
 
257
- // 🔹 Preparar instalación
248
+ function copyContextComponentIfNeeded(component, destComponents, overwrite = true) {
249
+ if (!CONTEXT_DEPENDENCIES[component]) return;
250
+
251
+ const contextSrc = path.join(COMPONENTS_DIR, "context", `${component}.tsx`);
252
+ const contextDest = path.join(process.cwd(), destComponents, "context", `${component}.tsx`);
253
+ copyFile(contextSrc, contextDest, `Context de "${component}"`, overwrite);
254
+ }
255
+
258
256
  for (const mainComponent of componentsCapitalized) {
259
257
  const componentPath = path.join(process.cwd(), options.dest, `${mainComponent}.tsx`);
260
258
  let overwriteMain = true;
261
259
 
262
- // Preguntar solo si el componente principal existe
263
260
  if (fs.existsSync(componentPath)) {
264
261
  const { overwrite } = await inquirer.prompt([
265
262
  {
@@ -276,10 +273,10 @@ program
276
273
  }
277
274
  }
278
275
 
279
- // 🔹 Copiar componente principal
280
276
  copyComponentAndRecipe(mainComponent, options.dest, options.theme, overwriteMain);
281
277
 
282
- // 🔹 Copiar dependencias (sin sobrescribir si existen)
278
+ copyContextComponentIfNeeded(mainComponent, options.dest, overwriteMain);
279
+
283
280
  const deps = componentToDeps[mainComponent] || [];
284
281
  for (const dep of deps) {
285
282
  const depPath = path.join(process.cwd(), options.dest, `${dep}.tsx`);
@@ -291,7 +288,6 @@ program
291
288
  copyComponentAndRecipe(dep, options.dest, options.theme, true);
292
289
  }
293
290
 
294
- // 🔹 Copiar íconos dependientes
295
291
  const iconDeps = ICON_DEPENDENCIES[mainComponent] || [];
296
292
  if (iconDeps.length > 0) {
297
293
  console.log(`🎨 Añadiendo íconos requeridos por "${mainComponent}": ${iconDeps.join(", ")}`);
@@ -305,7 +301,6 @@ program
305
301
  copyIconTemplate(iconName, options.icons);
306
302
  }
307
303
 
308
- // Asegurar que IconWrapper esté disponible
309
304
  ensureIconWrapper(options.dest, options.theme);
310
305
  }
311
306
  }
@@ -336,9 +331,6 @@ function copyIconTemplate(iconName, dest) {
336
331
  }
337
332
  }
338
333
 
339
- /**
340
- * Copia IconWrapper si no existe en la app
341
- */
342
334
  function ensureIconWrapper(destComponents, destTheme) {
343
335
  const wrapperComponentDest = path.join(process.cwd(), destComponents, "IconWrapper.tsx");
344
336
  const wrapperRecipeDest = path.join(process.cwd(), destTheme, "IconWrapper.recipe.tsx");
@@ -363,7 +355,6 @@ function ensureIconWrapper(destComponents, destTheme) {
363
355
  }
364
356
  }
365
357
 
366
- // Comando CLI: add-icon
367
358
  program
368
359
  .command("add-icon [iconName]")
369
360
  .description("Copia un icono basado en la plantilla Icon.tsx")
@@ -381,7 +372,6 @@ program
381
372
  const finalName = rawName.charAt(0).toUpperCase() + rawName.slice(1);
382
373
  const destPath = path.join(process.cwd(), options.dest, `${finalName}.tsx`);
383
374
 
384
- // 🔹 Si ya existe, preguntar antes de sobrescribir
385
375
  if (fs.existsSync(destPath)) {
386
376
  const { overwrite } = await inquirer.prompt([
387
377
  {
@@ -0,0 +1,113 @@
1
+ import React, {ReactNode, useState} from 'react'
2
+ import {View, Pressable} from 'react-native'
3
+ import Animated from 'react-native-reanimated'
4
+ import {LinearTransition} from 'react-native-reanimated'
5
+ import {StyleSheet} from 'react-native-unistyles'
6
+ import Text from './Text'
7
+
8
+ type AccordionItemProps = {
9
+ title: string
10
+ itemKey: string
11
+ children: ReactNode
12
+ isOpen?: boolean
13
+ onToggle?: () => void
14
+ scrollViewRef?: any
15
+ }
16
+
17
+ type AccordionGroupRootProps = {
18
+ children: ReactNode
19
+ defaultOpenKeys?: string[]
20
+ allowMultiple?: boolean
21
+ }
22
+
23
+ export const AccordionGroup = {
24
+ Root: AccordionGroupRoot,
25
+ Item: AccordionGroupItem,
26
+ }
27
+
28
+ function AccordionGroupRoot({
29
+ children,
30
+ defaultOpenKeys = [],
31
+ allowMultiple = false,
32
+ }: AccordionGroupRootProps) {
33
+ const [openKeys, setOpenKeys] = useState<Set<string>>(
34
+ () => new Set(defaultOpenKeys),
35
+ )
36
+
37
+ const toggleItem = (key: string) => {
38
+ setOpenKeys(prev => {
39
+ const newSet = new Set(prev)
40
+ if (newSet.has(key)) {
41
+ newSet.delete(key)
42
+ } else {
43
+ if (allowMultiple) {
44
+ newSet.add(key)
45
+ } else {
46
+ return new Set([key])
47
+ }
48
+ }
49
+ return newSet
50
+ })
51
+ }
52
+
53
+ const items = React.Children.map(children, child => {
54
+ if (!React.isValidElement(child)) return child
55
+ const cp = child.props as AccordionItemProps
56
+ const key = cp.itemKey
57
+ const isOpen = openKeys.has(key)
58
+ return React.cloneElement(child, {
59
+ isOpen,
60
+ onToggle: () => toggleItem(key),
61
+ })
62
+ })
63
+
64
+ return <View style={styles.groupContainer}>{items}</View>
65
+ }
66
+
67
+ function AccordionGroupItem({
68
+ title,
69
+ children,
70
+ isOpen = false,
71
+ onToggle,
72
+ }: AccordionItemProps) {
73
+ return (
74
+ <Animated.View
75
+ // Aquí aplicas la transición de layout
76
+ layout={LinearTransition.duration(150)}
77
+ style={styles.itemContainer}>
78
+ <Pressable onPress={onToggle} style={styles.header}>
79
+ <Text style={styles.headerText}>{title}</Text>
80
+ </Pressable>
81
+
82
+ {isOpen && (
83
+ <View style={styles.contentContainer}>
84
+ <View style={styles.innerContent}>{children}</View>
85
+ </View>
86
+ )}
87
+ </Animated.View>
88
+ )
89
+ }
90
+
91
+ const styles = StyleSheet.create({
92
+ groupContainer: {},
93
+ itemContainer: {
94
+ borderWidth: 1,
95
+ borderColor: '#ddd',
96
+ borderRadius: 6,
97
+ marginVertical: 8,
98
+ overflow: 'hidden', // importante para que no se vea contenido fuera
99
+ },
100
+ header: {
101
+ padding: 12,
102
+ backgroundColor: '#f0f0f0',
103
+ },
104
+ headerText: {
105
+ fontSize: 16,
106
+ },
107
+ contentContainer: {
108
+ // no necesitamos animar altura manual, lo hace el layout
109
+ },
110
+ innerContent: {
111
+ padding: 12,
112
+ },
113
+ })
@@ -10,6 +10,12 @@ type TextAdjustment = 'singleLine' | 'multiline' | 'adjustToFit'
10
10
 
11
11
  type ButtonVariants = UnistylesVariants<typeof ButtonStyles>
12
12
 
13
+ interface TextAdjustmentProps {
14
+ adjustsFontSizeToFit?: boolean
15
+ numberOfLines?: number
16
+ ellipsizeMode?: 'tail' | 'head' | 'middle' | 'clip'
17
+ }
18
+
13
19
  type ButtonProps = ButtonVariants & {
14
20
  colorPalette?: PalettesWithNestedKeys
15
21
  text?: string
@@ -27,6 +33,7 @@ type ButtonProps = ButtonVariants & {
27
33
  size?: number
28
34
  }
29
35
  mixins?: StyleProp<ViewStyle> | StyleProp<ViewStyle>[]
36
+ style?: StyleProp<ViewStyle>
30
37
  }
31
38
 
32
39
  const Button = ({
@@ -42,6 +49,7 @@ const Button = ({
42
49
  textAdjustment = 'singleLine',
43
50
  icon,
44
51
  mixins,
52
+ style,
45
53
  }: ButtonProps) => {
46
54
  ButtonStyles.useVariants({
47
55
  size,
@@ -50,7 +58,7 @@ const Button = ({
50
58
  })
51
59
 
52
60
  const getTextProps = useMemo(
53
- () => (): Record<string, any> => {
61
+ () => (): TextAdjustmentProps => {
54
62
  switch (textAdjustment) {
55
63
  case 'adjustToFit':
56
64
  return {adjustsFontSizeToFit: true, numberOfLines: 1}
@@ -87,6 +95,7 @@ const Button = ({
87
95
  styles.container(flex, maxWidth),
88
96
  ButtonStyles.container(colorPalette),
89
97
  mixins && mixins,
98
+ style,
90
99
  ]}
91
100
  onPress={onPress}
92
101
  disabled={disabled || loading}>
@@ -1,5 +1,5 @@
1
1
  import {useEffect} from 'react'
2
- import {View, StyleSheet} from 'react-native'
2
+ import {TextStyle, View, ViewStyle} from 'react-native'
3
3
  import Animated, {
4
4
  Easing,
5
5
  interpolate,
@@ -10,9 +10,15 @@ import Animated, {
10
10
  } from 'react-native-reanimated'
11
11
  import Svg, {Circle, G} from 'react-native-svg'
12
12
  import {circleProgressTokens} from '../theme/CircleProgress.recipe'
13
- import {withUnistyles} from 'react-native-unistyles'
13
+ import {withUnistyles, StyleSheet} from 'react-native-unistyles'
14
14
  import {resolveColor} from '../style/varia/utils'
15
- import {PalettesWithNestedKeys} from '../style/varia/types'
15
+ import {
16
+ NestedColorsType,
17
+ PalettesWithNestedKeys,
18
+ progressDirection,
19
+ rotationDirection,
20
+ ThemeType,
21
+ } from '../style/varia/types'
16
22
  import {SharedValue} from 'react-native-reanimated'
17
23
 
18
24
  const AnimatedCircle = Animated.createAnimatedComponent(Circle)
@@ -22,17 +28,19 @@ interface CircleProgressProps {
22
28
  variant?: keyof typeof circleProgressTokens.variants.variant
23
29
  size?: keyof typeof circleProgressTokens.variants.size
24
30
  trackStrokeWidth?: number
25
- progress: SharedValue<number> // ✅ Nuevo
26
-
31
+ progress: SharedValue<number>
27
32
  progressStrokeWidth?: number
28
33
  duration: number
29
34
  trackColor?: string
30
35
  progressColor?: string
31
- progressDirection?: 'forward' | 'reverse'
32
- rotationDirection?: 'clockwise' | 'counterclockwise'
36
+ progressDirection?: progressDirection
37
+ rotationDirection?: rotationDirection
33
38
  children?: React.ReactNode
34
- fontSize?: number | undefined
35
- colors: any
39
+ fontSize?: TextStyle['fontSize']
40
+ colors: NestedColorsType
41
+ flex?: ViewStyle['flex']
42
+ width?: ViewStyle['width']
43
+ height?: ViewStyle['height']
36
44
  }
37
45
 
38
46
  const BaseCircleProgress = ({
@@ -49,6 +57,9 @@ const BaseCircleProgress = ({
49
57
  rotationDirection = 'clockwise',
50
58
  children,
51
59
  colors,
60
+ flex = 1,
61
+ width = '100%',
62
+ height,
52
63
  }: CircleProgressProps) => {
53
64
  const resolvedSize = circleProgressTokens.variants.size[size]
54
65
 
@@ -106,7 +117,7 @@ const BaseCircleProgress = ({
106
117
  })
107
118
 
108
119
  return (
109
- <View style={styles.container}>
120
+ <View style={styles.container(flex, width, height)}>
110
121
  <Svg
111
122
  width="100%"
112
123
  height="100%"
@@ -143,16 +154,17 @@ const BaseCircleProgress = ({
143
154
  }
144
155
 
145
156
  const styles = StyleSheet.create({
146
- container: {
157
+ container: (
158
+ flex: ViewStyle['flex'],
159
+ width: ViewStyle['width'],
160
+ height: ViewStyle['height'],
161
+ ) => ({
147
162
  aspectRatio: 1,
148
- flex: 1,
149
- },
163
+ flex,
164
+ maxWidth: width,
165
+ maxHeight: height,
166
+ }),
150
167
  childContainer: {
151
- position: 'absolute',
152
- top: 0,
153
- left: 0,
154
- right: 0,
155
- bottom: 0,
156
168
  justifyContent: 'center',
157
169
  alignItems: 'center',
158
170
  },
@@ -163,6 +175,3 @@ const CircleProgress = withUnistyles(BaseCircleProgress, theme => ({
163
175
  }))
164
176
 
165
177
  export default CircleProgress
166
-
167
- const clamp = (num: number, min: number, max: number) =>
168
- Math.min(Math.max(num, min), max)
@@ -1,24 +1,27 @@
1
- import { View } from 'react-native';
2
- import { StyleSheet } from 'react-native-unistyles';
3
- // import type { VariaThemeType } from '../style/theme';
1
+ import {View} from 'react-native'
2
+ import {StyleSheet} from 'react-native-unistyles'
3
+ import {PalettesWithNestedKeys, ThemeColors} from '../style/varia/types'
4
+ import {resolveColor} from '../style/varia/utils'
4
5
 
5
6
  const Divider = ({
6
7
  color,
7
8
  size = 1,
8
9
  axis = 'y',
9
10
  margin = 0,
11
+ colorPalette = 'accent',
10
12
  }: {
11
- color?: string;
12
- size?: number;
13
- axis?: 'x' | 'y';
14
- margin?: number;
13
+ color?: ThemeColors
14
+ size?: number
15
+ axis?: 'x' | 'y'
16
+ margin?: number
17
+ colorPalette?: PalettesWithNestedKeys
15
18
  }) => {
16
19
  return (
17
20
  <View style={styles.container(size, axis, margin)}>
18
- <View style={[styles.divider(color, size, axis)]} />
21
+ <View style={[styles.divider(color, colorPalette, size, axis)]} />
19
22
  </View>
20
- );
21
- };
23
+ )
24
+ }
22
25
 
23
26
  const styles = StyleSheet.create(theme => ({
24
27
  container: (size, axis, margin) => ({
@@ -31,13 +34,13 @@ const styles = StyleSheet.create(theme => ({
31
34
  marginHorizontal: axis === 'x' ? margin : 0,
32
35
  marginVertical: axis === 'y' ? margin : 0,
33
36
  }),
34
- divider: (color, size, axis) => ({
37
+ divider: (color, colorPalette, size, axis) => ({
35
38
  width: axis === 'x' ? size : '100%',
36
39
  height: axis === 'y' ? size : '100%',
37
40
  backgroundColor: color
38
- ? color
39
- : theme.colors.foreground,
41
+ ? resolveColor(color, theme.colors, colorPalette)
42
+ : theme.colors.fg.default,
40
43
  }),
41
- }));
44
+ }))
42
45
 
43
- export default Divider;
46
+ export default Divider
@@ -202,7 +202,6 @@ type InternalDrawerSliderProps = {
202
202
  externalTranslate?: SharedValue<number>
203
203
  }
204
204
 
205
- // Tipo público — el que exportas (sin direction)
206
205
  export type DrawerSliderProps = Omit<
207
206
  InternalDrawerSliderProps,
208
207
  'direction' | 'axis'
@@ -238,7 +237,6 @@ const DrawerSliderInternal = ({
238
237
  const animationVariant = SlidingDrawerTokens.variants.animation[animation]
239
238
  const VELOCITY_THRESHOLD = 2000
240
239
 
241
- // --- shared values base ---
242
240
  const viewRef = useAnimatedRef<Animated.View>()
243
241
  const translate = useSharedValue(screenHeight)
244
242
  const context = useSharedValue({position: screenHeight, snapPoint: 0})
@@ -254,37 +252,7 @@ const DrawerSliderInternal = ({
254
252
  )
255
253
  }
256
254
 
257
- // --- medir el contenido dinámicamente ---
258
- // const onLayout = () => {
259
- // scheduleOnUI(() => {
260
- // 'worklet'
261
- // const measured = measure(viewRef)
262
- // if (measured) {
263
- // const {height} = measured
264
- // contentHeight.value = height
265
-
266
- // // resuelve snapPoints declarativos
267
- // const resolved = snapPoints.map(p => {
268
- // if (p === 'hidden') return screenHeight * direction
269
- // if (p === 'content') return (screenHeight - height) * direction
270
- // // if (typeof p === 'string' && p.endsWith('%')) {
271
- // // const percentage = parseFloat(p) / 100
272
- // // return screenHeight * (1 - percentage) * direction
273
- // // }
274
- // return p * direction
275
- // })
276
-
277
- // resolvedSnapPoints.value = resolved
278
-
279
- // // inicializa la posición (oculto)
280
- // translate.value = resolved[0]
281
- // context.value = {position: resolved[0], snapPoint: 0}
282
- // }
283
- // })
284
- // }
285
-
286
255
  const onLayout = () => {
287
- // captura valores aquí (en JS)
288
256
  const _screenHeight = screenHeight
289
257
  const _screenWidth = screenWidth
290
258
  const _axis = axis
@@ -316,10 +284,13 @@ const DrawerSliderInternal = ({
316
284
  'worklet'
317
285
  return resolvedSnapPoints.value.length > 0
318
286
  ? resolvedSnapPoints.value
319
- : snapPoints.map(p => (p as any) * direction)
287
+ : snapPoints.map(p => {
288
+ // if (p === 'hidden') return screenHeight * direction
289
+ // if (p === 'content') return (screenHeight - contentHeight.value) * direction
290
+ return (p as number) * direction
291
+ })
320
292
  }
321
293
 
322
- // --- lógica de snapping ---
323
294
  const updateCurrentSnapPoint = (snapPoint: number) => {
324
295
  'worklet'
325
296
  context.value = {position: context.value.position, snapPoint}
@@ -374,7 +345,6 @@ const DrawerSliderInternal = ({
374
345
  isCollapsed,
375
346
  }))
376
347
 
377
- // --- sincronizar overlay con movimiento ---
378
348
  useAnimatedReaction(
379
349
  () => translate.value,
380
350
  value => {
@@ -392,7 +362,6 @@ const DrawerSliderInternal = ({
392
362
  },
393
363
  )
394
364
 
395
- // --- Gestures ---
396
365
  const slideGesture = Gesture.Pan()
397
366
  .enabled(allowGestures)
398
367
  .onBegin(() => {
@@ -408,16 +377,13 @@ const DrawerSliderInternal = ({
408
377
 
409
378
  if (proposed < minPoint) {
410
379
  if (lockAtEdges) {
411
- // Bloquea overscroll superior (cuando ya estás en el extremo)
412
380
  clamped = minPoint
413
381
  } else {
414
- // Aplica resistencia
415
382
  const overdrag = minPoint - proposed
416
383
  clamped = minPoint - overdrag / (1 + overdrag / 60)
417
384
  }
418
385
  } else if (proposed > maxPoint) {
419
386
  if (lockAtEdges) {
420
- // Bloquea overscroll inferior
421
387
  clamped = maxPoint
422
388
  } else {
423
389
  const overdrag = proposed - maxPoint
@@ -477,7 +443,6 @@ const DrawerSliderInternal = ({
477
443
  }
478
444
  })
479
445
 
480
- // --- estilos animados ---
481
446
  const blockAnimatedStyle = useAnimatedStyle(() => {
482
447
  return {
483
448
  transform: [
@@ -504,10 +469,6 @@ const DrawerSliderInternal = ({
504
469
  )
505
470
  }
506
471
 
507
- /* -----------------------------
508
- * Export grouped
509
- * ----------------------------*/
510
-
511
472
  export const Drawer = {
512
473
  Root: DrawerRoot,
513
474
  Positioner: DrawerPositioner,
@@ -515,10 +476,6 @@ export const Drawer = {
515
476
  Slider: DrawerSlider,
516
477
  }
517
478
 
518
- /* -----------------------------
519
- * Styles
520
- * ----------------------------*/
521
-
522
479
  const styles = StyleSheet.create((theme, rt) => ({
523
480
  positioner: {
524
481
  flex: 1,