@william-callao/antonella-ui 1.0.0 → 1.0.2

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 (3) hide show
  1. package/dist/index.d.ts +31 -9
  2. package/dist/index.js +480 -383
  3. package/package.json +33 -33
package/dist/index.js CHANGED
@@ -123,6 +123,7 @@ __export(index_exports, {
123
123
  resolveComposition: () => resolveComposition,
124
124
  resolveTransition: () => resolveTransition,
125
125
  updateNode: () => updateNode,
126
+ useAppLayoutDebug: () => useAppLayoutDebug,
126
127
  useAppNavigation: () => useAppNavigation,
127
128
  useSheetLayout: () => useSheetLayout,
128
129
  useToast: () => useToast
@@ -237,7 +238,9 @@ var iconMap = {
237
238
  file: import_lucide_react_native.File,
238
239
  loader: import_lucide_react_native.LoaderCircle,
239
240
  inbox: import_lucide_react_native.Inbox,
240
- "triangle-alert": import_lucide_react_native.TriangleAlert
241
+ "triangle-alert": import_lucide_react_native.TriangleAlert,
242
+ eye: import_lucide_react_native.Eye,
243
+ "eye-off": import_lucide_react_native.EyeOff
241
244
  };
242
245
  var STROKE_WIDTH = 2.25;
243
246
  function Icon({ name, size = 20, color, style, testID }) {
@@ -374,28 +377,31 @@ function Button({
374
377
  size = "md",
375
378
  style,
376
379
  disabled,
380
+ loading = false,
377
381
  android_ripple,
378
382
  ...rest
379
383
  }) {
380
384
  const defaultRipple = android_ripple ?? {
381
385
  color: variant === "primary" || variant === "danger" ? "rgba(255, 255, 255, 0.2)" : "rgba(0, 0, 0, 0.08)"
382
386
  };
387
+ const isDisabled = disabled === true || loading;
383
388
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
384
389
  import_react_native5.Pressable,
385
390
  {
386
391
  accessibilityRole: "button",
387
- disabled,
388
- android_ripple: disabled ? void 0 : defaultRipple,
392
+ accessibilityState: { disabled: isDisabled, busy: loading },
393
+ disabled: isDisabled,
394
+ android_ripple: isDisabled ? void 0 : defaultRipple,
389
395
  style: ({ pressed }) => [
390
396
  styles4.base,
391
397
  sizeStyles[size],
392
398
  variantStyles[variant],
393
- pressed && !disabled && styles4.pressed,
399
+ pressed && !isDisabled && styles4.pressed,
394
400
  disabled && styles4.disabled,
395
401
  style
396
402
  ],
397
403
  ...rest,
398
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
404
+ children: loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.ActivityIndicator, { color: labelColors[variant], size: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
399
405
  import_react_native5.Text,
400
406
  {
401
407
  style: [
@@ -412,7 +418,7 @@ function Button({
412
418
  }
413
419
  var styles4 = import_react_native5.StyleSheet.create({
414
420
  base: {
415
- borderRadius: 10,
421
+ borderRadius: 999,
416
422
  alignItems: "center",
417
423
  justifyContent: "center"
418
424
  },
@@ -423,9 +429,9 @@ var styles4 = import_react_native5.StyleSheet.create({
423
429
  labelDisabled: { opacity: 0.6 }
424
430
  });
425
431
  var sizeStyles = import_react_native5.StyleSheet.create({
426
- sm: { paddingVertical: 6, paddingHorizontal: 12 },
427
- md: { paddingVertical: 10, paddingHorizontal: 16 },
428
- lg: { paddingVertical: 14, paddingHorizontal: 20 }
432
+ sm: { height: 36, paddingHorizontal: 12 },
433
+ md: { height: 44, paddingHorizontal: 16 },
434
+ lg: { height: 54, paddingHorizontal: 20 }
429
435
  });
430
436
  var variantStyles = import_react_native5.StyleSheet.create({
431
437
  primary: { backgroundColor: import_antonella_theme5.palette.primary },
@@ -1027,7 +1033,8 @@ function HeaderBar({
1027
1033
  description,
1028
1034
  style = "DEFAULT" /* DEFAULT */,
1029
1035
  onMenuPress,
1030
- menuIcon = "menu"
1036
+ menuIcon = "menu",
1037
+ accessibilityLabel = "Abrir men\xFA"
1031
1038
  }) {
1032
1039
  const c = STYLE_COLORS3[style];
1033
1040
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native14.View, { style: styles13.container, children: [
@@ -1041,7 +1048,7 @@ function HeaderBar({
1041
1048
  { backgroundColor: pressed ? c.buttonPressedBg : c.buttonBg }
1042
1049
  ],
1043
1050
  accessibilityRole: "button",
1044
- accessibilityLabel: "Abrir men\xFA",
1051
+ accessibilityLabel,
1045
1052
  children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, { name: menuIcon, size: 22, color: c.iconColor })
1046
1053
  }
1047
1054
  ),
@@ -1439,6 +1446,7 @@ function BottomSheet({
1439
1446
  const insets = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
1440
1447
  const keyboardHeight = useModalKeyboardHeight();
1441
1448
  const [mounted, setMounted] = (0, import_react5.useState)(visible);
1449
+ const [contentReady, setContentReady] = (0, import_react5.useState)(false);
1442
1450
  const progress = (0, import_react_native_reanimated3.useSharedValue)(0);
1443
1451
  const maxHeightRatio = (0, import_react5.useMemo)(() => {
1444
1452
  let ratio = 0.9;
@@ -1453,6 +1461,13 @@ function BottomSheet({
1453
1461
  (0, import_react5.useEffect)(() => {
1454
1462
  if (visible) setMounted(true);
1455
1463
  }, [visible]);
1464
+ (0, import_react5.useEffect)(() => {
1465
+ if (mounted && visible) {
1466
+ const raf = requestAnimationFrame(() => setContentReady(true));
1467
+ return () => cancelAnimationFrame(raf);
1468
+ }
1469
+ if (!mounted) setContentReady(false);
1470
+ }, [mounted, visible]);
1456
1471
  (0, import_react5.useEffect)(() => {
1457
1472
  if (!mounted) return;
1458
1473
  if (visible) {
@@ -1518,28 +1533,34 @@ function BottomSheet({
1518
1533
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_reanimated3.default.View, { style: [styles18.backdrop, backdropStyle] })
1519
1534
  }
1520
1535
  ),
1521
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_reanimated3.default.View, { style: [styles18.panelWrapper, containerAnimatedStyle], pointerEvents: "box-none", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react_native_reanimated3.default.View, { style: [styles18.panel, panelHeightStyle, panelStyle], children: [
1522
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native20.View, { style: styles18.handleBar }),
1523
- title || icon || caption || showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1524
- DialogHeader,
1525
- {
1526
- icon,
1527
- title,
1528
- caption,
1529
- onClose,
1530
- showCloseButton
1531
- }
1532
- ) : null,
1533
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1534
- import_react_native20.ScrollView,
1535
- {
1536
- showsVerticalScrollIndicator: false,
1537
- keyboardShouldPersistTaps: "handled",
1538
- contentContainerStyle: [styles18.content, contentStyle],
1539
- children
1540
- }
1541
- )
1542
- ] }) })
1536
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native_reanimated3.default.View, { style: [styles18.panelWrapper, containerAnimatedStyle], pointerEvents: "box-none", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1537
+ import_react_native_reanimated3.default.View,
1538
+ {
1539
+ style: [styles18.panel, panelHeightStyle, panelStyle],
1540
+ children: [
1541
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native20.View, { style: styles18.handleBar }),
1542
+ title || icon || caption || showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1543
+ DialogHeader,
1544
+ {
1545
+ icon,
1546
+ title,
1547
+ caption,
1548
+ onClose,
1549
+ showCloseButton
1550
+ }
1551
+ ) : null,
1552
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1553
+ import_react_native20.ScrollView,
1554
+ {
1555
+ showsVerticalScrollIndicator: false,
1556
+ keyboardShouldPersistTaps: "handled",
1557
+ contentContainerStyle: [styles18.content, contentStyle],
1558
+ children: contentReady ? children : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native20.View, { style: styles18.deferredPlaceholder })
1559
+ }
1560
+ )
1561
+ ]
1562
+ }
1563
+ ) })
1543
1564
  ] })
1544
1565
  }
1545
1566
  );
@@ -1575,6 +1596,9 @@ var styles18 = import_react_native20.StyleSheet.create({
1575
1596
  content: {
1576
1597
  paddingTop: import_antonella_theme19.space.space2,
1577
1598
  paddingBottom: Math.max(import_antonella_theme19.space.space3, 24)
1599
+ },
1600
+ deferredPlaceholder: {
1601
+ minHeight: import_antonella_theme19.space.space16
1578
1602
  }
1579
1603
  });
1580
1604
 
@@ -1596,12 +1620,14 @@ function CardStackSheet({
1596
1620
  dismissible = true,
1597
1621
  children,
1598
1622
  contentStyle,
1599
- snapPoints
1623
+ snapPoints,
1624
+ areaColor
1600
1625
  }) {
1601
1626
  const { height: screenHeight } = (0, import_react_native21.useWindowDimensions)();
1602
1627
  const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
1603
1628
  const keyboardHeight = useModalKeyboardHeight();
1604
1629
  const [mounted, setMounted] = (0, import_react6.useState)(visible);
1630
+ const [contentReady, setContentReady] = (0, import_react6.useState)(false);
1605
1631
  const progress = (0, import_react_native_reanimated4.useSharedValue)(0);
1606
1632
  const maxHeightRatio = (0, import_react6.useMemo)(() => {
1607
1633
  let ratio = 0.9;
@@ -1616,6 +1642,13 @@ function CardStackSheet({
1616
1642
  (0, import_react6.useEffect)(() => {
1617
1643
  if (visible) setMounted(true);
1618
1644
  }, [visible]);
1645
+ (0, import_react6.useEffect)(() => {
1646
+ if (mounted && visible) {
1647
+ const raf = requestAnimationFrame(() => setContentReady(true));
1648
+ return () => cancelAnimationFrame(raf);
1649
+ }
1650
+ if (!mounted) setContentReady(false);
1651
+ }, [mounted, visible]);
1619
1652
  (0, import_react6.useEffect)(() => {
1620
1653
  if (!mounted) return;
1621
1654
  if (visible) {
@@ -1691,8 +1724,12 @@ function CardStackSheet({
1691
1724
  {
1692
1725
  showsVerticalScrollIndicator: false,
1693
1726
  keyboardShouldPersistTaps: "handled",
1694
- contentContainerStyle: [styles19.content, contentStyle],
1695
- children
1727
+ contentContainerStyle: [
1728
+ styles19.content,
1729
+ contentStyle,
1730
+ areaColor ? { backgroundColor: areaColor } : void 0
1731
+ ],
1732
+ children: contentReady ? children : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_native21.View, { style: styles19.deferredPlaceholder })
1696
1733
  }
1697
1734
  ) })
1698
1735
  }
@@ -1721,6 +1758,9 @@ var styles19 = import_react_native21.StyleSheet.create({
1721
1758
  content: {
1722
1759
  gap: import_antonella_theme20.space.space3,
1723
1760
  paddingBottom: Math.max(import_antonella_theme20.space.space3, 24)
1761
+ },
1762
+ deferredPlaceholder: {
1763
+ minHeight: import_antonella_theme20.space.space16
1724
1764
  }
1725
1765
  });
1726
1766
 
@@ -1824,12 +1864,12 @@ function Toast({
1824
1864
  {
1825
1865
  style: [
1826
1866
  styles21.toast,
1827
- { backgroundColor: c.bg, paddingTop: topInset + BASE_VPAD },
1867
+ { backgroundColor: c.bg, marginTop: (topInset || 0) + BASE_VPAD },
1828
1868
  containerStyle
1829
1869
  ],
1830
1870
  children: [
1831
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, { name: TONE_ICONS[tone], size: 18, color: c.content }),
1832
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Text, { variant: import_antonella_theme22.TextType.Caption, color: c.content, style: styles21.message, children: message }),
1871
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, { name: TONE_ICONS[tone], size: 20, color: c.content }),
1872
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Text, { variant: import_antonella_theme22.TextType.Body, color: c.content, style: styles21.message, children: message }),
1833
1873
  onClose ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1834
1874
  import_react_native23.Pressable,
1835
1875
  {
@@ -1838,7 +1878,7 @@ function Toast({
1838
1878
  accessibilityRole: "button",
1839
1879
  accessibilityLabel: "Cerrar aviso",
1840
1880
  style: ({ pressed }) => [styles21.close, pressed && styles21.closePressed],
1841
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, { name: "close", size: 15, color: c.content })
1881
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, { name: "close", size: 16, color: c.content })
1842
1882
  }
1843
1883
  ) : null
1844
1884
  ]
@@ -1863,14 +1903,14 @@ var STYLE_COLORS6 = {
1863
1903
  };
1864
1904
  var styles21 = import_react_native23.StyleSheet.create({
1865
1905
  toast: {
1866
- width: "100%",
1906
+ minHeight: 52,
1867
1907
  flexDirection: "row",
1868
1908
  alignItems: "center",
1869
1909
  gap: import_antonella_theme22.space.space2,
1870
- minHeight: 52,
1871
- borderRadius: 0,
1872
- paddingVertical: import_antonella_theme22.space.space3 + 2,
1910
+ borderRadius: 16,
1911
+ paddingVertical: import_antonella_theme22.space.space3,
1873
1912
  paddingHorizontal: import_antonella_theme22.space.space4,
1913
+ marginHorizontal: import_antonella_theme22.space.space4,
1874
1914
  shadowColor: "#000000",
1875
1915
  shadowOpacity: 0.25,
1876
1916
  shadowRadius: 10,
@@ -5078,68 +5118,163 @@ var styles39 = import_react_native43.StyleSheet.create({
5078
5118
  });
5079
5119
 
5080
5120
  // src/components/Input.tsx
5121
+ var import_react20 = require("react");
5081
5122
  var import_react_native44 = require("react-native");
5082
5123
  var import_antonella_theme41 = require("@william-callao/antonella-theme");
5083
5124
  var import_jsx_runtime44 = require("react/jsx-runtime");
5084
- function Input({ style, placeholderTextColor, icon, ...rest }) {
5085
- if (icon) {
5086
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react_native44.View, { style: [styles40.inputContainer, style], children: [
5087
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Icon, { name: icon, size: 18, color: import_antonella_theme41.text.secondary, style: styles40.icon }),
5088
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5089
- import_react_native44.TextInput,
5090
- {
5091
- placeholderTextColor: placeholderTextColor ?? import_antonella_theme41.appInput.placeholder,
5092
- style: styles40.inputFlex,
5093
- ...rest
5094
- }
5095
- )
5096
- ] });
5097
- }
5098
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5125
+ var INPUT_RADIUS = 16;
5126
+ function Input({
5127
+ style,
5128
+ inputStyle,
5129
+ placeholderTextColor,
5130
+ icon,
5131
+ showToggle,
5132
+ error,
5133
+ secureTextEntry = false,
5134
+ onFocus,
5135
+ onBlur,
5136
+ ...rest
5137
+ }) {
5138
+ const [focused, setFocused] = (0, import_react20.useState)(false);
5139
+ const [visible, setVisible] = (0, import_react20.useState)(false);
5140
+ const isSecure = secureTextEntry === true;
5141
+ const effectiveSecure = isSecure && !visible;
5142
+ const showEye = showToggle === true && isSecure;
5143
+ const hasDecorations = icon != null || showEye;
5144
+ const hasError = Boolean(error);
5145
+ const borderColor = hasError ? import_antonella_theme41.appInput.error : focused ? import_antonella_theme41.text.secondary : import_antonella_theme41.appInputCard.border;
5146
+ const toggleVisible = () => setVisible((prev) => !prev);
5147
+ const field = hasDecorations ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
5148
+ import_react_native44.View,
5149
+ {
5150
+ style: [
5151
+ styles40.container,
5152
+ { borderColor },
5153
+ showEye ? styles40.eyeContainer : null,
5154
+ style
5155
+ ],
5156
+ children: [
5157
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Icon, { name: icon, size: 18, color: import_antonella_theme41.text.secondary, style: styles40.sideIcon }) : null,
5158
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5159
+ import_react_native44.TextInput,
5160
+ {
5161
+ placeholderTextColor: placeholderTextColor ?? import_antonella_theme41.appInput.placeholder,
5162
+ style: [styles40.field, inputStyle],
5163
+ secureTextEntry: effectiveSecure,
5164
+ onFocus: (e) => {
5165
+ setFocused(true);
5166
+ onFocus?.(e);
5167
+ },
5168
+ onBlur: (e) => {
5169
+ setFocused(false);
5170
+ onBlur?.(e);
5171
+ },
5172
+ ...rest
5173
+ }
5174
+ ),
5175
+ showEye ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5176
+ import_react_native44.Pressable,
5177
+ {
5178
+ onPress: toggleVisible,
5179
+ hitSlop: 8,
5180
+ style: styles40.toggle,
5181
+ accessibilityRole: "button",
5182
+ accessibilityLabel: effectiveSecure ? "Mostrar contrase\xF1a" : "Ocultar contrase\xF1a",
5183
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5184
+ Icon,
5185
+ {
5186
+ name: effectiveSecure ? "eye" : "eye-off",
5187
+ size: 20,
5188
+ color: import_antonella_theme41.text.secondary
5189
+ }
5190
+ )
5191
+ }
5192
+ ) : null
5193
+ ]
5194
+ }
5195
+ ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5099
5196
  import_react_native44.TextInput,
5100
5197
  {
5101
5198
  placeholderTextColor: placeholderTextColor ?? import_antonella_theme41.appInput.placeholder,
5102
- style: [styles40.input, style],
5199
+ style: [
5200
+ styles40.input,
5201
+ { borderColor },
5202
+ inputStyle
5203
+ ],
5204
+ secureTextEntry,
5205
+ onFocus: (e) => {
5206
+ setFocused(true);
5207
+ onFocus?.(e);
5208
+ },
5209
+ onBlur: (e) => {
5210
+ setFocused(false);
5211
+ onBlur?.(e);
5212
+ },
5103
5213
  ...rest
5104
5214
  }
5105
5215
  );
5216
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react_native44.View, { style: styles40.wrapper, children: [
5217
+ field,
5218
+ hasError ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Text, { variant: import_antonella_theme41.TextType.Caption, color: import_antonella_theme41.appInput.error, style: styles40.error, children: error }) : null
5219
+ ] });
5106
5220
  }
5107
5221
  var styles40 = import_react_native44.StyleSheet.create({
5108
5222
  input: {
5109
- borderRadius: 10,
5110
- paddingHorizontal: import_antonella_theme41.spacing.md,
5223
+ borderWidth: 1,
5224
+ borderColor: import_antonella_theme41.appInputCard.border,
5225
+ borderRadius: INPUT_RADIUS,
5226
+ paddingLeft: import_antonella_theme41.space.space5,
5227
+ paddingRight: import_antonella_theme41.spacing.xl,
5111
5228
  paddingVertical: import_antonella_theme41.spacing.sm,
5112
5229
  fontSize: import_antonella_theme41.texts.caption.fontSize,
5113
5230
  lineHeight: import_antonella_theme41.texts.caption.lineHeight,
5114
5231
  color: import_antonella_theme41.appInput.text,
5115
5232
  backgroundColor: import_antonella_theme41.appInput.background
5116
5233
  },
5117
- inputContainer: {
5234
+ container: {
5118
5235
  flexDirection: "row",
5119
5236
  alignItems: "center",
5120
- borderRadius: 10,
5121
- paddingHorizontal: import_antonella_theme41.spacing.md,
5122
- backgroundColor: import_antonella_theme41.appInput.background
5237
+ borderWidth: 1,
5238
+ borderColor: import_antonella_theme41.appInputCard.border,
5239
+ borderRadius: INPUT_RADIUS,
5240
+ paddingHorizontal: import_antonella_theme41.spacing.lg,
5241
+ backgroundColor: import_antonella_theme41.appInput.background,
5242
+ overflow: "hidden"
5123
5243
  },
5124
- icon: {
5125
- marginRight: import_antonella_theme41.spacing.sm
5244
+ eyeContainer: {
5245
+ paddingRight: 0
5126
5246
  },
5127
- inputFlex: {
5247
+ field: {
5128
5248
  flex: 1,
5129
5249
  paddingVertical: import_antonella_theme41.spacing.sm,
5130
5250
  fontSize: import_antonella_theme41.texts.caption.fontSize,
5131
5251
  lineHeight: import_antonella_theme41.texts.caption.lineHeight,
5132
5252
  color: import_antonella_theme41.appInput.text
5253
+ },
5254
+ sideIcon: {
5255
+ marginRight: import_antonella_theme41.spacing.sm
5256
+ },
5257
+ toggle: {
5258
+ marginLeft: import_antonella_theme41.spacing.xs,
5259
+ paddingRight: import_antonella_theme41.spacing.lg,
5260
+ paddingVertical: import_antonella_theme41.spacing.xs,
5261
+ justifyContent: "center"
5262
+ },
5263
+ wrapper: {
5264
+ alignItems: "stretch"
5265
+ },
5266
+ error: {
5267
+ marginTop: import_antonella_theme41.spacing.xs
5133
5268
  }
5134
5269
  });
5135
5270
 
5136
5271
  // src/components/LayoutRow.tsx
5137
- var import_react20 = require("react");
5272
+ var import_react21 = require("react");
5138
5273
  var import_react_native45 = require("react-native");
5139
5274
  var import_antonella_theme42 = require("@william-callao/antonella-theme");
5140
5275
  var import_jsx_runtime45 = require("react/jsx-runtime");
5141
- var LayoutRowContext = (0, import_react20.createContext)({ debug: false, isSmall: false });
5142
- var useLayoutRowContext = () => (0, import_react20.useContext)(LayoutRowContext);
5276
+ var LayoutRowContext = (0, import_react21.createContext)({ debug: false, isSmall: false });
5277
+ var useLayoutRowContext = () => (0, import_react21.useContext)(LayoutRowContext);
5143
5278
  var debugColors = ["#FF6B6B", "#4ECDC4"];
5144
5279
  var BREAKPOINT_SMALL = 600;
5145
5280
  function LayoutRowFirst({ size = import_antonella_theme42.LayoutRowSize.EXPAND, scroll, children }) {
@@ -5198,12 +5333,12 @@ var styles41 = {
5198
5333
  };
5199
5334
 
5200
5335
  // src/components/LayoutColumn.tsx
5201
- var import_react21 = require("react");
5336
+ var import_react22 = require("react");
5202
5337
  var import_react_native46 = require("react-native");
5203
5338
  var import_antonella_theme43 = require("@william-callao/antonella-theme");
5204
5339
  var import_jsx_runtime46 = require("react/jsx-runtime");
5205
- var LayoutColumnContext = (0, import_react21.createContext)({ debug: false });
5206
- var useLayoutColumnContext = () => (0, import_react21.useContext)(LayoutColumnContext);
5340
+ var LayoutColumnContext = (0, import_react22.createContext)({ debug: false });
5341
+ var useLayoutColumnContext = () => (0, import_react22.useContext)(LayoutColumnContext);
5207
5342
  var debugColors2 = ["#FF6B6B", "#4ECDC4"];
5208
5343
  function LayoutColumnFirst({ size = import_antonella_theme43.LayoutColumnSize.EXPAND, scroll, children }) {
5209
5344
  const { debug } = useLayoutColumnContext();
@@ -5308,7 +5443,7 @@ var styles42 = import_react_native47.StyleSheet.create({
5308
5443
  });
5309
5444
 
5310
5445
  // src/components/ToolsCard.tsx
5311
- var import_react22 = __toESM(require("react"));
5446
+ var import_react23 = __toESM(require("react"));
5312
5447
  var import_react_native48 = require("react-native");
5313
5448
  var import_antonella_theme45 = require("@william-callao/antonella-theme");
5314
5449
  var import_jsx_runtime50 = require("react/jsx-runtime");
@@ -5318,7 +5453,7 @@ function ToolsCard({ tools, style }) {
5318
5453
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Icon, { name: tool.icon, size: 16, color: import_antonella_theme45.card.text.primary }),
5319
5454
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Text, { variant: import_antonella_theme45.TextType.BodyMedium, color: import_antonella_theme45.card.text.primary, numberOfLines: 1, children: tool.label })
5320
5455
  ] });
5321
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react22.default.Fragment, { children: [
5456
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react23.default.Fragment, { children: [
5322
5457
  index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_react_native48.View, { style: styles43.separator }) : null,
5323
5458
  tool.onPress ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
5324
5459
  import_react_native48.Pressable,
@@ -5362,7 +5497,7 @@ var styles43 = import_react_native48.StyleSheet.create({
5362
5497
  });
5363
5498
 
5364
5499
  // src/components/TreeEditor.tsx
5365
- var import_react23 = require("react");
5500
+ var import_react24 = __toESM(require("react"));
5366
5501
  var import_react_native49 = require("react-native");
5367
5502
  var import_antonella_theme46 = require("@william-callao/antonella-theme");
5368
5503
  var import_jsx_runtime51 = require("react/jsx-runtime");
@@ -5463,14 +5598,6 @@ function markBranchCollapsed(nodes, acc) {
5463
5598
  markBranchCollapsed(n.children, acc);
5464
5599
  }
5465
5600
  }
5466
- function findSiblingGroup(nodes, id) {
5467
- if (nodes.some((n) => n.id === id)) return nodes;
5468
- for (const n of nodes) {
5469
- const found = findSiblingGroup(n.children, id);
5470
- if (found) return found;
5471
- }
5472
- return null;
5473
- }
5474
5601
  function hasCode(nodes, code, excludeId) {
5475
5602
  for (const n of nodes) {
5476
5603
  if (n.code === code && n.id !== excludeId) return true;
@@ -5501,21 +5628,9 @@ var CARD_MARGIN = 12;
5501
5628
  var CARD_PADDING_H = import_antonella_theme46.space.space4;
5502
5629
  var CARD_RADIUS3 = 24;
5503
5630
  var LINE_X = 10;
5504
- var EXPAND_DURATION = 220;
5505
5631
  var EXPAND_FADE = 180;
5506
- var COLLAPSE_FADE = 120;
5507
5632
  var NODE_ICON_SIZE = 18;
5508
- function buildRows(nodes, depth, collapsed, out) {
5509
- nodes.forEach((node) => {
5510
- out.push({ node, depth });
5511
- const isCollapsed = !!collapsed[node.id];
5512
- if (node.children.length > 0 && !isCollapsed) {
5513
- buildRows(node.children, depth + 1, collapsed, out);
5514
- }
5515
- });
5516
- return out;
5517
- }
5518
- function NodeGutter({
5633
+ var NodeGutter = import_react24.default.memo(function NodeGutter2({
5519
5634
  depth,
5520
5635
  lineColor,
5521
5636
  terminal
@@ -5545,8 +5660,9 @@ function NodeGutter({
5545
5660
  );
5546
5661
  }
5547
5662
  return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_jsx_runtime51.Fragment, { children: columns });
5548
- }
5663
+ });
5549
5664
  function renderForest(ctx, nodes, depth, parentName) {
5665
+ const collapsed = ctx.getCollapsed();
5550
5666
  return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_jsx_runtime51.Fragment, { children: nodes.map((node, i) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
5551
5667
  TreeNodeItem,
5552
5668
  {
@@ -5554,55 +5670,48 @@ function renderForest(ctx, nodes, depth, parentName) {
5554
5670
  depth,
5555
5671
  isLast: i === nodes.length - 1,
5556
5672
  parentName,
5673
+ isCollapsed: !!collapsed[node.id],
5674
+ branchVersion: ctx.getVersion(node.id),
5557
5675
  ctx
5558
5676
  },
5559
5677
  node.id
5560
5678
  )) });
5561
5679
  }
5562
- function TreeNodeItem({
5680
+ function markDirtyPath(id, parentMap, acc) {
5681
+ let curr = id;
5682
+ while (curr) {
5683
+ acc.add(curr);
5684
+ curr = parentMap.get(curr);
5685
+ }
5686
+ }
5687
+ function markSubtreeDirty(node, acc) {
5688
+ acc.add(node.id);
5689
+ for (const child of node.children) markSubtreeDirty(child, acc);
5690
+ }
5691
+ var TreeNodeItem = import_react24.default.memo(function TreeNodeItem2({
5563
5692
  node,
5564
5693
  depth,
5565
5694
  isLast,
5566
5695
  parentName,
5696
+ isCollapsed,
5697
+ branchVersion,
5567
5698
  ctx
5568
5699
  }) {
5569
5700
  const hasChildren = node.children.length > 0;
5570
- const isCollapsed = !!ctx.collapsed[node.id];
5571
5701
  const isActive = hasChildren && !isCollapsed;
5572
5702
  const terminalElbow = isLast;
5573
- const subtreeRows = [];
5574
- buildRows(node.children, depth + 1, ctx.collapsed, subtreeRows);
5575
- const expandedHeight = (0, import_react23.useMemo)(
5576
- () => subtreeRows.length * (ROW_HEIGHT + CARD_MARGIN) + 2,
5577
- [subtreeRows.length]
5578
- );
5579
- const heightAnim = (0, import_react23.useRef)(new import_react_native49.Animated.Value(isCollapsed ? 0 : expandedHeight)).current;
5580
- const contentOpacity = (0, import_react23.useRef)(new import_react_native49.Animated.Value(isCollapsed ? 0 : 1)).current;
5581
- const measured = (0, import_react23.useRef)(false);
5582
- (0, import_react23.useEffect)(() => {
5583
- if (!measured.current) {
5584
- measured.current = true;
5585
- heightAnim.setValue(isCollapsed ? 0 : expandedHeight);
5586
- contentOpacity.setValue(isCollapsed ? 0 : 1);
5587
- return;
5588
- }
5589
- const toHeight = isCollapsed ? 0 : expandedHeight;
5590
- const animation = import_react_native49.Animated.parallel([
5591
- import_react_native49.Animated.timing(heightAnim, {
5592
- toValue: toHeight,
5593
- duration: EXPAND_DURATION,
5594
- easing: import_react_native49.Easing.out(import_react_native49.Easing.cubic),
5595
- useNativeDriver: false
5596
- }),
5597
- import_react_native49.Animated.timing(contentOpacity, {
5598
- toValue: isCollapsed ? 0 : 1,
5599
- duration: isCollapsed ? COLLAPSE_FADE : EXPAND_FADE,
5600
- useNativeDriver: false
5601
- })
5602
- ]);
5703
+ const contentOpacity = (0, import_react24.useRef)(new import_react_native49.Animated.Value(0)).current;
5704
+ (0, import_react24.useEffect)(() => {
5705
+ if (isCollapsed) return;
5706
+ const animation = import_react_native49.Animated.timing(contentOpacity, {
5707
+ toValue: 1,
5708
+ duration: EXPAND_FADE,
5709
+ easing: import_react_native49.Easing.out(import_react_native49.Easing.quad),
5710
+ useNativeDriver: true
5711
+ });
5603
5712
  animation.start();
5604
5713
  return () => animation.stop();
5605
- }, [isCollapsed, expandedHeight]);
5714
+ }, [isCollapsed, node.id, node.name, contentOpacity]);
5606
5715
  const defaultContent = /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: styles44.textBlock, children: [
5607
5716
  /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: styles44.titleRow, children: [
5608
5717
  /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
@@ -5689,20 +5798,66 @@ function TreeNodeItem({
5689
5798
  }
5690
5799
  ) : null
5691
5800
  ] }),
5692
- hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.Animated.View, { style: [styles44.subtree, { height: heightAnim }], children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.Animated.View, { style: { opacity: contentOpacity }, children: renderForest(ctx, node.children, depth + 1, node.name) }) }) : null
5801
+ hasChildren && !isCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.Animated.View, { style: [styles44.subtreeFade, { opacity: contentOpacity }], children: renderForest(ctx, node.children, depth + 1, node.name) }) : null
5693
5802
  ] });
5694
- }
5803
+ });
5695
5804
  function TreeEditor({ value, onChange, mode = "view", variant = "default", collapsed: collapsedProp, onCollapsedChange, rootLabel = "Agregar ra\xEDz", renderNode, onRequestAdd, onRequestEdit, onRequestDelete, style }) {
5696
- const t0 = performance.now();
5697
- const [internalCollapsed, setInternalCollapsed] = (0, import_react23.useState)({});
5805
+ const [internalCollapsed, setInternalCollapsed] = (0, import_react24.useState)({});
5698
5806
  const source = collapsedProp ?? internalCollapsed;
5699
5807
  const needsImplicitInit = value.length > 0 && Object.keys(source).length === 0;
5700
- const implicitInit = (0, import_react23.useMemo)(
5808
+ const implicitInit = (0, import_react24.useMemo)(
5701
5809
  () => needsImplicitInit ? buildInitialCollapsed(value) : null,
5702
5810
  [needsImplicitInit, value]
5703
5811
  );
5704
5812
  const collapsed = implicitInit ?? source;
5705
- (0, import_react23.useEffect)(() => {
5813
+ const parentMap = (0, import_react24.useMemo)(() => {
5814
+ const map = /* @__PURE__ */ new Map();
5815
+ const walk = (list, parent) => {
5816
+ for (const n of list) {
5817
+ if (parent) map.set(n.id, parent);
5818
+ walk(n.children, n.id);
5819
+ }
5820
+ };
5821
+ walk(value);
5822
+ return map;
5823
+ }, [value]);
5824
+ const collapsedRef = (0, import_react24.useRef)(collapsed);
5825
+ collapsedRef.current = collapsed;
5826
+ const valueRef = (0, import_react24.useRef)(value);
5827
+ valueRef.current = value;
5828
+ const onCollapsedChangeRef = (0, import_react24.useRef)(onCollapsedChange);
5829
+ onCollapsedChangeRef.current = onCollapsedChange;
5830
+ const onRequestEditRef = (0, import_react24.useRef)(onRequestEdit);
5831
+ onRequestEditRef.current = onRequestEdit;
5832
+ const controlledRef = (0, import_react24.useRef)(collapsedProp !== void 0);
5833
+ const versionRef = (0, import_react24.useRef)(/* @__PURE__ */ new Map());
5834
+ const renderSeqRef = (0, import_react24.useRef)(0);
5835
+ const prevCollapsedRef = (0, import_react24.useRef)(collapsed);
5836
+ const parentMapRef = (0, import_react24.useRef)(parentMap);
5837
+ parentMapRef.current = parentMap;
5838
+ {
5839
+ const versions = versionRef.current;
5840
+ const dirty = /* @__PURE__ */ new Set();
5841
+ const prev = prevCollapsedRef.current;
5842
+ const markChange = (id) => {
5843
+ markDirtyPath(id, parentMapRef.current, dirty);
5844
+ const node = findNode(value, id);
5845
+ if (node) markSubtreeDirty(node, dirty);
5846
+ };
5847
+ for (const id of Object.keys(collapsed)) {
5848
+ if (prev[id] !== collapsed[id]) markChange(id);
5849
+ }
5850
+ for (const id of Object.keys(prev)) {
5851
+ if (prev[id] === true && !(id in collapsed)) markChange(id);
5852
+ }
5853
+ prevCollapsedRef.current = collapsed;
5854
+ if (dirty.size > 0) {
5855
+ renderSeqRef.current += 1;
5856
+ const seq = renderSeqRef.current;
5857
+ for (const id of dirty) versions.set(id, seq);
5858
+ }
5859
+ }
5860
+ (0, import_react24.useEffect)(() => {
5706
5861
  if (implicitInit == null) return;
5707
5862
  if (collapsedProp != null) {
5708
5863
  onCollapsedChange?.(implicitInit);
@@ -5712,67 +5867,66 @@ function TreeEditor({ value, onChange, mode = "view", variant = "default", colla
5712
5867
  }, [implicitInit]);
5713
5868
  const vt = VARIANT_TOKENS[variant];
5714
5869
  const isEdit = mode === "edit";
5715
- const ctx = {
5716
- isEdit,
5717
- collapsed,
5718
- onToggle: toggleCollapse,
5719
- onOpenActions: (nodeId) => {
5720
- const node = findNode(value, nodeId);
5721
- if (node) onRequestEdit?.(node);
5722
- },
5723
- renderNode,
5724
- vt
5725
- };
5726
- function toggleCollapse(id) {
5727
- const collapsing = !collapsed[id];
5870
+ const getCollapsed = (0, import_react24.useCallback)(() => collapsedRef.current, []);
5871
+ const getVersion = (0, import_react24.useCallback)((id) => versionRef.current.get(id) ?? 0, []);
5872
+ const toggleCollapse = (0, import_react24.useCallback)((id) => {
5873
+ const collapseMap = collapsedRef.current;
5874
+ const tree = valueRef.current;
5875
+ const collapsing = !collapseMap[id];
5728
5876
  let next;
5729
5877
  if (collapsing) {
5730
- next = { ...collapsed, [id]: true };
5731
- const node = findNode(value, id);
5878
+ next = { ...collapseMap, [id]: true };
5879
+ const node = findNode(tree, id);
5732
5880
  if (node) markBranchCollapsed(node.children, next);
5733
5881
  } else {
5734
- next = { ...collapsed, [id]: false };
5735
- const siblings = findSiblingGroup(value, id);
5736
- const rootId = value.length > 0 ? value[0].id : null;
5737
- if (siblings) {
5738
- for (const s of siblings) {
5739
- if (s.id !== id && s.id !== rootId && s.children.length > 0) {
5740
- next[s.id] = true;
5741
- markBranchCollapsed(s.children, next);
5742
- }
5743
- }
5744
- }
5882
+ next = { ...collapseMap, [id]: false };
5745
5883
  }
5746
- if (collapsedProp != null) {
5747
- onCollapsedChange?.(next);
5884
+ if (controlledRef.current) {
5885
+ onCollapsedChangeRef.current?.(next);
5748
5886
  } else {
5749
5887
  setInternalCollapsed(next);
5750
5888
  }
5751
- }
5752
- console.log("[TreeEditor] render", Math.round(performance.now() - t0), "ms", {
5753
- valueLen: value.length,
5754
- mode,
5755
- variant,
5756
- collapsedKeys: Object.keys(collapsed).length
5757
- });
5758
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_react_native49.View, { style: [styles44.container, { backgroundColor: vt.containerBg }, style], children: [
5759
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { children: renderForest(ctx, value, 0) }),
5760
- isEdit ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5761
- import_react_native49.Pressable,
5762
- {
5763
- onPress: () => onRequestAdd?.(null),
5764
- style: ({ pressed }) => [
5765
- styles44.addRoot,
5766
- pressed && { backgroundColor: vt.pressedBg }
5767
- ],
5768
- accessibilityRole: "button",
5769
- children: [
5770
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { style: [styles44.addChip, { borderColor: vt.addRootText }], children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Icon, { name: "add", size: 13, color: vt.addRootText }) }),
5771
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text, { variant: import_antonella_theme46.TextType.BodyMedium, color: vt.addRootText, children: rootLabel })
5772
- ]
5773
- }
5774
- ) : null
5775
- ] });
5889
+ }, []);
5890
+ const onOpenActions = (0, import_react24.useCallback)((nodeId) => {
5891
+ const node = findNode(valueRef.current, nodeId);
5892
+ if (node) onRequestEditRef.current?.(node);
5893
+ }, []);
5894
+ const ctx = (0, import_react24.useMemo)(
5895
+ () => ({
5896
+ isEdit,
5897
+ onToggle: toggleCollapse,
5898
+ onOpenActions,
5899
+ renderNode,
5900
+ vt,
5901
+ getCollapsed,
5902
+ getVersion
5903
+ }),
5904
+ [isEdit, toggleCollapse, onOpenActions, renderNode, vt, getCollapsed, getVersion]
5905
+ );
5906
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5907
+ import_react_native49.View,
5908
+ {
5909
+ style: [styles44.container, { backgroundColor: vt.containerBg }, style],
5910
+ children: [
5911
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { children: renderForest(ctx, value, 0) }),
5912
+ isEdit ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5913
+ import_react_native49.Pressable,
5914
+ {
5915
+ onPress: () => onRequestAdd?.(null),
5916
+ style: ({ pressed }) => [
5917
+ styles44.addRoot,
5918
+ pressed && { backgroundColor: vt.pressedBg }
5919
+ ],
5920
+ accessibilityRole: "button",
5921
+ children: [
5922
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native49.View, { style: [styles44.addChip, { borderColor: vt.addRootText }], children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Icon, { name: "add", size: 13, color: vt.addRootText }) }),
5923
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text, { variant: import_antonella_theme46.TextType.BodyMedium, color: vt.addRootText, children: rootLabel })
5924
+ ]
5925
+ }
5926
+ ) : null
5927
+ ]
5928
+ }
5929
+ );
5776
5930
  }
5777
5931
  var styles44 = import_react_native49.StyleSheet.create({
5778
5932
  container: {
@@ -5848,8 +6002,9 @@ var styles44 = import_react_native49.StyleSheet.create({
5848
6002
  marginBottom: CARD_MARGIN,
5849
6003
  borderRadius: import_antonella_theme46.radius.sm
5850
6004
  },
5851
- subtree: {
5852
- overflow: "hidden"
6005
+ subtreeFade: {
6006
+ // Fade puro (native driver): sin medir/animar altura, evita el layout en
6007
+ // cascada al expandir/colapsar subárboles anidados.
5853
6008
  },
5854
6009
  addChip: {
5855
6010
  width: 22,
@@ -6084,15 +6239,15 @@ var styles46 = import_react_native51.StyleSheet.create({
6084
6239
  });
6085
6240
 
6086
6241
  // src/components/card-form/AppFormCard.tsx
6087
- var import_react24 = __toESM(require("react"));
6242
+ var import_react25 = __toESM(require("react"));
6088
6243
  var import_react_native52 = require("react-native");
6089
6244
  var import_antonella_theme48 = require("@william-callao/antonella-theme");
6090
6245
  var import_jsx_runtime54 = require("react/jsx-runtime");
6091
6246
  function AppFormCard({ children, labelWidth, style }) {
6092
- const items = import_react24.default.Children.toArray(children).filter((child) => import_react24.default.isValidElement(child)).map((child) => child);
6247
+ const items = import_react25.default.Children.toArray(children).filter((child) => import_react25.default.isValidElement(child)).map((child) => child);
6093
6248
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native52.View, { style: [styles47.container, style], children: items.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native52.View, { style: styles47.row, children: [
6094
6249
  index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native52.View, { style: styles47.divider }) : null,
6095
- import_react24.default.cloneElement(child, {
6250
+ import_react25.default.cloneElement(child, {
6096
6251
  ...labelWidth != null ? { labelWidth } : {}
6097
6252
  })
6098
6253
  ] }, index)) });
@@ -6117,7 +6272,7 @@ var styles47 = import_react_native52.StyleSheet.create({
6117
6272
  });
6118
6273
 
6119
6274
  // src/components/card-form/AppTextInput.tsx
6120
- var import_react25 = require("react");
6275
+ var import_react26 = require("react");
6121
6276
  var import_react_native53 = require("react-native");
6122
6277
  var import_antonella_theme49 = require("@william-callao/antonella-theme");
6123
6278
  var import_jsx_runtime55 = require("react/jsx-runtime");
@@ -6133,8 +6288,8 @@ function AppTextInput({
6133
6288
  maxLength,
6134
6289
  editable = true
6135
6290
  }) {
6136
- const inputRef = (0, import_react25.useRef)(null);
6137
- const [inputHeight, setInputHeight] = (0, import_react25.useState)(void 0);
6291
+ const inputRef = (0, import_react26.useRef)(null);
6292
+ const [inputHeight, setInputHeight] = (0, import_react26.useState)(void 0);
6138
6293
  const focus = () => {
6139
6294
  if (editable) inputRef.current?.focus();
6140
6295
  };
@@ -6232,7 +6387,7 @@ var styles48 = import_react_native53.StyleSheet.create({
6232
6387
  });
6233
6388
 
6234
6389
  // src/components/card-form/AppTextArea.tsx
6235
- var import_react26 = require("react");
6390
+ var import_react27 = require("react");
6236
6391
  var import_react_native54 = require("react-native");
6237
6392
  var import_antonella_theme50 = require("@william-callao/antonella-theme");
6238
6393
  var import_jsx_runtime56 = require("react/jsx-runtime");
@@ -6248,8 +6403,8 @@ function AppTextArea({
6248
6403
  maxLength,
6249
6404
  editable = true
6250
6405
  }) {
6251
- const inputRef = (0, import_react26.useRef)(null);
6252
- const [inputHeight, setInputHeight] = (0, import_react26.useState)(void 0);
6406
+ const inputRef = (0, import_react27.useRef)(null);
6407
+ const [inputHeight, setInputHeight] = (0, import_react27.useState)(void 0);
6253
6408
  const focus = () => {
6254
6409
  if (editable) inputRef.current?.focus();
6255
6410
  };
@@ -6337,7 +6492,7 @@ var styles49 = import_react_native54.StyleSheet.create({
6337
6492
  });
6338
6493
 
6339
6494
  // src/components/card-form/AppSelector.tsx
6340
- var import_react27 = require("react");
6495
+ var import_react28 = require("react");
6341
6496
  var import_react_native55 = require("react-native");
6342
6497
  var import_antonella_theme51 = require("@william-callao/antonella-theme");
6343
6498
  var import_jsx_runtime57 = require("react/jsx-runtime");
@@ -6353,17 +6508,17 @@ function AppSelector({
6353
6508
  placeholder = "Seleccionar",
6354
6509
  disabled = false
6355
6510
  }) {
6356
- const [open, setOpen] = (0, import_react27.useState)(false);
6357
- const [contentHeight, setContentHeight] = (0, import_react27.useState)(0);
6358
- const chevron = (0, import_react27.useRef)(new import_react_native55.Animated.Value(0)).current;
6359
- const height = (0, import_react27.useRef)(new import_react_native55.Animated.Value(0)).current;
6360
- const contentOpacity = (0, import_react27.useRef)(new import_react_native55.Animated.Value(0)).current;
6511
+ const [open, setOpen] = (0, import_react28.useState)(false);
6512
+ const [contentHeight, setContentHeight] = (0, import_react28.useState)(0);
6513
+ const chevron = (0, import_react28.useRef)(new import_react_native55.Animated.Value(0)).current;
6514
+ const height = (0, import_react28.useRef)(new import_react_native55.Animated.Value(0)).current;
6515
+ const contentOpacity = (0, import_react28.useRef)(new import_react_native55.Animated.Value(0)).current;
6361
6516
  const selected = options.find((o) => o.value === value);
6362
- const chevronRotate = (0, import_react27.useMemo)(
6517
+ const chevronRotate = (0, import_react28.useMemo)(
6363
6518
  () => chevron.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"] }),
6364
6519
  [chevron]
6365
6520
  );
6366
- (0, import_react27.useEffect)(() => {
6521
+ (0, import_react28.useEffect)(() => {
6367
6522
  import_react_native55.Animated.timing(chevron, {
6368
6523
  toValue: open ? 1 : 0,
6369
6524
  duration: 180,
@@ -6371,7 +6526,7 @@ function AppSelector({
6371
6526
  useNativeDriver: false
6372
6527
  }).start();
6373
6528
  }, [open, chevron]);
6374
- (0, import_react27.useEffect)(() => {
6529
+ (0, import_react28.useEffect)(() => {
6375
6530
  const animation = import_react_native55.Animated.parallel([
6376
6531
  import_react_native55.Animated.timing(height, {
6377
6532
  toValue: open ? Math.max(contentHeight, options.length * OPTION_ROW_HEIGHT) : 0,
@@ -6506,7 +6661,7 @@ var styles50 = import_react_native55.StyleSheet.create({
6506
6661
  });
6507
6662
 
6508
6663
  // src/components/card-form/AppToggle.tsx
6509
- var import_react28 = require("react");
6664
+ var import_react29 = require("react");
6510
6665
  var import_react_native56 = require("react-native");
6511
6666
  var import_antonella_theme52 = require("@william-callao/antonella-theme");
6512
6667
  var import_jsx_runtime58 = require("react/jsx-runtime");
@@ -6522,9 +6677,9 @@ function AppToggle({
6522
6677
  onValueChange,
6523
6678
  disabled = false
6524
6679
  }) {
6525
- const thumbX = (0, import_react28.useRef)(new import_react_native56.Animated.Value(value ? 1 : 0)).current;
6526
- const trackColor = (0, import_react28.useRef)(new import_react_native56.Animated.Value(value ? 1 : 0)).current;
6527
- (0, import_react28.useEffect)(() => {
6680
+ const thumbX = (0, import_react29.useRef)(new import_react_native56.Animated.Value(value ? 1 : 0)).current;
6681
+ const trackColor = (0, import_react29.useRef)(new import_react_native56.Animated.Value(value ? 1 : 0)).current;
6682
+ (0, import_react29.useEffect)(() => {
6528
6683
  import_react_native56.Animated.parallel([
6529
6684
  import_react_native56.Animated.timing(thumbX, {
6530
6685
  toValue: value ? 1 : 0,
@@ -6725,13 +6880,13 @@ var styles53 = import_react_native58.StyleSheet.create({
6725
6880
  });
6726
6881
 
6727
6882
  // src/layout/SheetLayout.tsx
6728
- var import_react30 = require("react");
6883
+ var import_react31 = require("react");
6729
6884
  var import_react_native60 = require("react-native");
6730
6885
  var import_react_native_reanimated13 = __toESM(require("react-native-reanimated"));
6731
6886
  var import_antonella_theme55 = require("@william-callao/antonella-theme");
6732
6887
 
6733
6888
  // src/layout/SheetSlot.tsx
6734
- var import_react29 = require("react");
6889
+ var import_react30 = require("react");
6735
6890
  var import_react_native59 = require("react-native");
6736
6891
  var import_react_native_reanimated12 = __toESM(require("react-native-reanimated"));
6737
6892
  var import_react_native_safe_area_context10 = require("react-native-safe-area-context");
@@ -6759,7 +6914,7 @@ function SheetSlot({
6759
6914
  const fixedH = route?.options?.fixedHeaderHeight;
6760
6915
  const headerBg = route?.headerBackgroundColor ?? DEFAULT_HEADER_BG;
6761
6916
  const bodyBg = route?.bodyBackgroundColor ?? DEFAULT_BODY_BG;
6762
- const [measuredH, setMeasuredH] = (0, import_react29.useState)(fixedH ?? 0);
6917
+ const [measuredH, setMeasuredH] = (0, import_react30.useState)(fixedH ?? 0);
6763
6918
  const headerHAnim = (0, import_react_native_reanimated12.useSharedValue)(fixedH ?? 0);
6764
6919
  const scrollY = (0, import_react_native_reanimated12.useSharedValue)(0);
6765
6920
  const contentFade = (0, import_react_native_reanimated12.useSharedValue)(1);
@@ -6769,7 +6924,7 @@ function SheetSlot({
6769
6924
  setMeasuredH(h);
6770
6925
  headerHAnim.value = (0, import_react_native_reanimated12.withTiming)(h, { duration: 280 });
6771
6926
  };
6772
- (0, import_react29.useEffect)(() => {
6927
+ (0, import_react30.useEffect)(() => {
6773
6928
  scrollY.value = (0, import_react_native_reanimated12.withTiming)(0, { duration: 250 });
6774
6929
  contentFade.value = 0;
6775
6930
  contentFade.value = (0, import_react_native_reanimated12.withTiming)(1, { duration: 240 });
@@ -6966,12 +7121,12 @@ var _semantic8 = (0, import_antonella_theme55.resolveSemantic)(import_antonella_
6966
7121
  var HEADER_BG = _semantic8.default.bg.default;
6967
7122
  var BODY_BG = _semantic8.darkness.bg.default;
6968
7123
  var DURATION = 340;
6969
- var SheetLayoutContext = (0, import_react30.createContext)({
7124
+ var SheetLayoutContext = (0, import_react31.createContext)({
6970
7125
  change: () => {
6971
7126
  }
6972
7127
  });
6973
7128
  function useSheetLayout() {
6974
- return (0, import_react30.useContext)(SheetLayoutContext);
7129
+ return (0, import_react31.useContext)(SheetLayoutContext);
6975
7130
  }
6976
7131
  function resolveBaseColor(key) {
6977
7132
  return key === "header" ? HEADER_BG : BODY_BG;
@@ -6982,14 +7137,14 @@ function SheetLayout({
6982
7137
  onRequestChange,
6983
7138
  style
6984
7139
  }) {
6985
- const routeMap = (0, import_react30.useMemo)(() => {
7140
+ const routeMap = (0, import_react31.useMemo)(() => {
6986
7141
  const m = {};
6987
7142
  for (const r of routes) m[r.key] = r;
6988
7143
  return m;
6989
7144
  }, [routes]);
6990
7145
  const activeRoute = routeMap[activeKey];
6991
7146
  const comp = activeRoute ? resolveComposition(activeRoute.kind) : { host: "base", baseColor: "header" };
6992
- const [slots, setSlots] = (0, import_react30.useState)(() => {
7147
+ const [slots, setSlots] = (0, import_react31.useState)(() => {
6993
7148
  const init = {
6994
7149
  base: null,
6995
7150
  top: null,
@@ -7009,8 +7164,8 @@ function SheetLayout({
7009
7164
  const baseFrom = (0, import_react_native_reanimated13.useSharedValue)(HEADER_BG);
7010
7165
  const baseTo = (0, import_react_native_reanimated13.useSharedValue)(HEADER_BG);
7011
7166
  const baseProg = (0, import_react_native_reanimated13.useSharedValue)(1);
7012
- const prevKey = (0, import_react30.useRef)(activeKey);
7013
- (0, import_react30.useEffect)(() => {
7167
+ const prevKey = (0, import_react31.useRef)(activeKey);
7168
+ (0, import_react31.useEffect)(() => {
7014
7169
  if (activeRoute) {
7015
7170
  visBySide[comp.host].value = (0, import_react_native_reanimated13.withTiming)(1, { duration: DURATION });
7016
7171
  }
@@ -7019,7 +7174,7 @@ function SheetLayout({
7019
7174
  baseTo.value = c;
7020
7175
  baseProg.value = 1;
7021
7176
  }, []);
7022
- (0, import_react30.useEffect)(() => {
7177
+ (0, import_react31.useEffect)(() => {
7023
7178
  if (activeKey === prevKey.current) return;
7024
7179
  const toRoute = activeRoute;
7025
7180
  if (!toRoute) return;
@@ -7160,10 +7315,9 @@ var styles56 = import_react_native61.StyleSheet.create({
7160
7315
  });
7161
7316
 
7162
7317
  // src/layout/AppLayout.tsx
7163
- var import_react31 = require("react");
7318
+ var import_react32 = require("react");
7164
7319
  var import_react_native63 = require("react-native");
7165
7320
  var import_react_native64 = require("react-native");
7166
- var import_react_native_reanimated14 = __toESM(require("react-native-reanimated"));
7167
7321
 
7168
7322
  // src/layout/Divisor.tsx
7169
7323
  var import_react_native62 = require("react-native");
@@ -7263,25 +7417,30 @@ var DEFAULT_COLORS = {
7263
7417
  mid: DEFAULT_BG2,
7264
7418
  bottom: DARK_BG
7265
7419
  };
7266
- var COLLAPSE_DISTANCE = 80;
7267
- var TRANSITION = 320;
7268
- var AppNavigationContext = (0, import_react31.createContext)(null);
7420
+ var AppNavigationContext = (0, import_react32.createContext)(null);
7269
7421
  function useAppNavigation() {
7270
- const ctx = (0, import_react31.useContext)(AppNavigationContext);
7422
+ const ctx = (0, import_react32.useContext)(AppNavigationContext);
7271
7423
  if (!ctx) {
7272
7424
  throw new Error("useAppNavigation debe usarse dentro de <AppLayout>");
7273
7425
  }
7274
7426
  return ctx;
7275
7427
  }
7428
+ var AppLayoutDebugContext = (0, import_react32.createContext)(null);
7429
+ function useAppLayoutDebug() {
7430
+ const ctx = (0, import_react32.useContext)(AppLayoutDebugContext);
7431
+ if (!ctx) {
7432
+ throw new Error("useAppLayoutDebug debe usarse dentro de <AppLayout>");
7433
+ }
7434
+ return ctx;
7435
+ }
7276
7436
  function AppLayout({
7277
7437
  initialRoute,
7278
- showBackButton = true,
7279
- debug = false
7438
+ showBackButton = true
7280
7439
  }) {
7281
7440
  const { height: H } = (0, import_react_native64.useWindowDimensions)();
7282
- const [stack, setStack] = (0, import_react31.useState)([initialRoute]);
7283
- const [prevRoute, setPrevRoute] = (0, import_react31.useState)(null);
7284
- (0, import_react31.useEffect)(() => {
7441
+ const [stack, setStack] = (0, import_react32.useState)([initialRoute]);
7442
+ const [prevRoute, setPrevRoute] = (0, import_react32.useState)(null);
7443
+ (0, import_react32.useEffect)(() => {
7285
7444
  setStack((s) => {
7286
7445
  if (s[0]?.name !== initialRoute.name) {
7287
7446
  return [initialRoute];
@@ -7289,18 +7448,18 @@ function AppLayout({
7289
7448
  return s;
7290
7449
  });
7291
7450
  }, [initialRoute.name]);
7292
- const navigate = (0, import_react31.useCallback)((route) => {
7451
+ const navigate = (0, import_react32.useCallback)((route) => {
7293
7452
  setStack((s) => [...s, route]);
7294
7453
  }, []);
7295
- const replace = (0, import_react31.useCallback)((route) => {
7454
+ const replace = (0, import_react32.useCallback)((route) => {
7296
7455
  setStack((s) => [...s.slice(0, -1), route]);
7297
7456
  }, []);
7298
- const back = (0, import_react31.useCallback)(() => {
7457
+ const back = (0, import_react32.useCallback)(() => {
7299
7458
  setStack((s) => s.length > 1 ? s.slice(0, -1) : s);
7300
7459
  }, []);
7301
7460
  const canGoBack = stack.length > 1;
7302
7461
  const currentRoute = stack[stack.length - 1];
7303
- (0, import_react31.useEffect)(() => {
7462
+ (0, import_react32.useEffect)(() => {
7304
7463
  const sub = import_react_native63.BackHandler.addEventListener("hardwareBackPress", () => {
7305
7464
  if (canGoBack) {
7306
7465
  back();
@@ -7327,47 +7486,19 @@ function AppLayout({
7327
7486
  const bottomVisible = !!state.sections.bottom?.visible;
7328
7487
  const showTopDivisor = topVisible && (midVisible || bottomVisible);
7329
7488
  const showBottomDivisor = bottomVisible && (topVisible || midVisible);
7330
- const topNatural = (0, import_react_native_reanimated14.useSharedValue)(H / 3);
7331
- const midNatural = (0, import_react_native_reanimated14.useSharedValue)(H / 3);
7332
- const bottomNatural = (0, import_react_native_reanimated14.useSharedValue)(H / 3);
7333
- const naturals = {
7334
- top: topNatural,
7335
- mid: midNatural,
7336
- bottom: bottomNatural
7337
- };
7338
- const animating = (0, import_react_native_reanimated14.useSharedValue)(0);
7339
- const scrollY = (0, import_react_native_reanimated14.useSharedValue)(0);
7340
- const scrollRef = (0, import_react31.useRef)(null);
7341
- const innerScrollRef = (0, import_react31.useRef)(null);
7342
- const settleTimerRef = (0, import_react31.useRef)(null);
7343
- const progress = (0, import_react_native_reanimated14.useSharedValue)(1);
7344
- const fromH = {
7345
- top: (0, import_react_native_reanimated14.useSharedValue)(H / 3),
7346
- mid: (0, import_react_native_reanimated14.useSharedValue)(H / 3),
7347
- bottom: (0, import_react_native_reanimated14.useSharedValue)(H / 3)
7348
- };
7349
- const toH = {
7350
- top: (0, import_react_native_reanimated14.useSharedValue)(H / 3),
7351
- mid: (0, import_react_native_reanimated14.useSharedValue)(H / 3),
7352
- bottom: (0, import_react_native_reanimated14.useSharedValue)(H / 3)
7353
- };
7354
- const topDisplay = (0, import_react_native_reanimated14.useDerivedValue)(
7355
- () => (0, import_react_native_reanimated14.interpolate)(progress.value, [0, 1], [fromH.top.value, toH.top.value])
7356
- );
7357
- const midDisplay = (0, import_react_native_reanimated14.useDerivedValue)(
7358
- () => (0, import_react_native_reanimated14.interpolate)(progress.value, [0, 1], [fromH.mid.value, toH.mid.value])
7359
- );
7360
- const bottomDisplay = (0, import_react_native_reanimated14.useDerivedValue)(
7361
- () => (0, import_react_native_reanimated14.interpolate)(progress.value, [0, 1], [fromH.bottom.value, toH.bottom.value])
7362
- );
7363
- const display = {
7364
- top: topDisplay,
7365
- mid: midDisplay,
7366
- bottom: bottomDisplay
7367
- };
7368
- const onScroll = (0, import_react_native_reanimated14.useAnimatedScrollHandler)((event) => {
7369
- scrollY.value = event.contentOffset.y;
7489
+ const [layoutHeights, setLayoutHeights] = (0, import_react32.useState)({
7490
+ top: H / 3,
7491
+ mid: H / 3,
7492
+ bottom: H / 3
7370
7493
  });
7494
+ const scrollRef = (0, import_react32.useRef)(null);
7495
+ const innerScrollRef = (0, import_react32.useRef)(null);
7496
+ const naturalsRef = (0, import_react32.useRef)({
7497
+ top: H / 3,
7498
+ mid: H / 3,
7499
+ bottom: H / 3
7500
+ });
7501
+ const lastMeasured = (0, import_react32.useRef)({ top: 0, mid: 0, bottom: 0 });
7371
7502
  const computeTargets = (st) => {
7372
7503
  const base = { top: 0, mid: 0, bottom: 0 };
7373
7504
  for (const k of SECTION_KEYS) {
@@ -7377,103 +7508,68 @@ function AppLayout({
7377
7508
  continue;
7378
7509
  }
7379
7510
  const h = b.height ?? "content";
7380
- if (h === "content") base[k] = naturals[k].value;
7511
+ if (h === "content") base[k] = naturalsRef.current[k];
7381
7512
  else if (h === "third") base[k] = H / 3;
7382
7513
  else if (h === "fill") base[k] = H;
7383
- else if (h === "fillRest") base[k] = b.restsOn ? H - naturals[b.restsOn].value : 0;
7514
+ else if (h === "fillRest") base[k] = b.restsOn ? H - naturalsRef.current[b.restsOn] : 0;
7384
7515
  else base[k] = h;
7385
7516
  }
7386
7517
  return base;
7387
7518
  };
7519
+ const applyTargets = (0, import_react32.useCallback)((next) => {
7520
+ setLayoutHeights(
7521
+ (prev) => SECTION_KEYS.every((k) => prev[k] === next[k]) ? prev : next
7522
+ );
7523
+ }, []);
7388
7524
  const makeOnMeasure = (k) => (e) => {
7389
7525
  const h = e.nativeEvent.layout.height;
7390
- naturals[k].value = h;
7391
- const b = state.sections[k];
7392
- if (b?.height === "content") {
7393
- fromH[k].value = display[k].value;
7394
- toH[k].value = h;
7395
- }
7396
- for (const j of SECTION_KEYS) {
7397
- const bj = state.sections[j];
7398
- if (bj?.visible && bj.height === "fillRest" && bj.restsOn === k) {
7399
- fromH[j].value = display[j].value;
7400
- toH[j].value = H - h;
7401
- }
7402
- }
7526
+ const prev = lastMeasured.current[k];
7527
+ const collapsed = prev > 0 && h < Math.min(prev * 0.5, 100);
7528
+ if (collapsed) return;
7529
+ naturalsRef.current[k] = h;
7530
+ lastMeasured.current[k] = h;
7531
+ applyTargets(computeTargets(state));
7403
7532
  };
7404
- (0, import_react31.useLayoutEffect)(() => {
7405
- if (settleTimerRef.current) clearTimeout(settleTimerRef.current);
7406
- animating.value = 1;
7533
+ (0, import_react32.useLayoutEffect)(() => {
7534
+ const targets = computeTargets(state);
7407
7535
  if (!state.pageScroll) {
7408
7536
  scrollRef.current?.scrollTo({ y: 0, animated: false });
7409
7537
  innerScrollRef.current?.scrollTo({ y: 0, animated: false });
7410
- scrollY.value = 0;
7411
- }
7412
- const targets = computeTargets(state);
7413
- for (const k of SECTION_KEYS) {
7414
- fromH[k].value = display[k].value;
7415
- toH[k].value = targets[k];
7416
- }
7417
- progress.value = 0;
7418
- progress.value = (0, import_react_native_reanimated14.withTiming)(
7419
- 1,
7420
- { duration: TRANSITION, easing: import_react_native_reanimated14.Easing.inOut(import_react_native_reanimated14.Easing.cubic) },
7421
- () => {
7422
- animating.value = 0;
7423
- }
7424
- );
7425
- settleTimerRef.current = setTimeout(() => {
7426
- scrollRef.current?.scrollTo({ y: 0, animated: false });
7427
- scrollY.value = 0;
7428
- setPrevRoute(currentRoute);
7429
- }, TRANSITION);
7430
- if (debug) {
7431
- console.log("[APP] transition ->", currentRoute.name, targets);
7432
7538
  }
7539
+ applyTargets(targets);
7540
+ setPrevRoute(currentRoute);
7433
7541
  }, [currentRoute.name]);
7434
- const topStyle = (0, import_react_native_reanimated14.useAnimatedStyle)(() => ({ height: topDisplay.value }));
7435
- const midStyle = (0, import_react_native_reanimated14.useAnimatedStyle)(() => ({ height: midDisplay.value }));
7436
- const bottomStyle = (0, import_react_native_reanimated14.useAnimatedStyle)(() => ({ height: bottomDisplay.value }));
7437
- const stylesFor = {
7438
- top: topStyle,
7439
- mid: midStyle,
7440
- bottom: bottomStyle
7441
- };
7442
- const topFade = (0, import_react_native_reanimated14.useAnimatedStyle)(
7542
+ const snapshot = (0, import_react32.useCallback)(
7443
7543
  () => {
7444
- const scrollFade = state.sections.top?.fadeOnScroll ? (0, import_react_native_reanimated14.interpolate)(scrollY.value, [0, COLLAPSE_DISTANCE], [1, 0], import_react_native_reanimated14.Extrapolation.CLAMP) : 1;
7445
- return { opacity: scrollFade };
7446
- },
7447
- [state]
7448
- );
7449
- const midFade = (0, import_react_native_reanimated14.useAnimatedStyle)(
7450
- () => {
7451
- const scrollFade = state.sections.mid?.fadeOnScroll ? (0, import_react_native_reanimated14.interpolate)(scrollY.value, [0, COLLAPSE_DISTANCE], [1, 0], import_react_native_reanimated14.Extrapolation.CLAMP) : 1;
7452
- const full = naturals.mid.value || 1;
7453
- const collapseFade = (0, import_react_native_reanimated14.interpolate)(midDisplay.value, [0, full], [0, 1], import_react_native_reanimated14.Extrapolation.CLAMP);
7454
- return { opacity: Math.min(scrollFade, collapseFade) };
7455
- },
7456
- [state]
7457
- );
7458
- const bottomFade = (0, import_react_native_reanimated14.useAnimatedStyle)(
7459
- () => {
7460
- const scrollFade = state.sections.bottom?.fadeOnScroll ? (0, import_react_native_reanimated14.interpolate)(scrollY.value, [0, COLLAPSE_DISTANCE], [1, 0], import_react_native_reanimated14.Extrapolation.CLAMP) : 1;
7461
- return { opacity: scrollFade };
7544
+ const midNatural = naturalsRef.current.mid || 1;
7545
+ return {
7546
+ route: currentRoute.name,
7547
+ anchors: stack.map((r) => r.name),
7548
+ anim: {
7549
+ scrollY: 0,
7550
+ animating: 0,
7551
+ top: Math.round(layoutHeights.top),
7552
+ mid: Math.round(layoutHeights.mid),
7553
+ bottom: Math.round(layoutHeights.bottom),
7554
+ topFade: 1,
7555
+ midFade: Math.min(layoutHeights.mid / midNatural, 1),
7556
+ bottomFade: 1
7557
+ },
7558
+ naturals: { ...naturalsRef.current },
7559
+ lastMeasured: { ...lastMeasured.current },
7560
+ windowH: H
7561
+ };
7462
7562
  },
7463
- [state]
7563
+ [currentRoute.name, stack, H, layoutHeights]
7464
7564
  );
7465
- const fadeFor = {
7466
- top: topFade,
7467
- mid: midFade,
7468
- bottom: bottomFade
7469
- };
7470
7565
  const renderSection = (k) => {
7471
7566
  const cur = state.sections[k];
7472
7567
  const prevB = prevLayoutState?.sections[k];
7473
7568
  const prevVisible = !!prevB?.visible;
7474
7569
  const visible = !!cur?.visible || prevVisible;
7570
+ const height = layoutHeights[k];
7475
7571
  if (!visible) {
7476
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native_reanimated14.default.View, { style: [styles58.colBlock, stylesFor[k]], children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: styles58.measureCopy, onLayout: makeOnMeasure(k), children: cur?.slot ? slots[cur.slot] : null }) }, k);
7572
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: [styles58.colBlock, { height }], children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: styles58.measureCopy, onLayout: makeOnMeasure(k), children: cur?.slot ? slots[cur.slot] : null }) }, k);
7477
7573
  }
7478
7574
  const usePrevContent = !cur?.visible && prevVisible;
7479
7575
  const slot = usePrevContent ? prevB?.slot : cur?.slot;
@@ -7481,39 +7577,36 @@ function AppLayout({
7481
7577
  const bg = cur?.backgroundColor ?? prevB?.backgroundColor ?? DEFAULT_COLORS[k];
7482
7578
  const isDynamic = (cur?.height ?? prevB?.height) === "content";
7483
7579
  const scroll = cur?.scroll ?? prevB?.scroll ?? false;
7484
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
7485
- import_react_native_reanimated14.default.View,
7486
- {
7487
- style: [styles58.colBlock, { backgroundColor: bg, overflow: "hidden" }, stylesFor[k]],
7488
- children: [
7489
- isDynamic && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: styles58.measureCopy, onLayout: makeOnMeasure(k), children: content }),
7490
- scroll ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
7491
- import_react_native_reanimated14.default.ScrollView,
7492
- {
7493
- ref: innerScrollRef,
7494
- style: styles58.innerScroll,
7495
- showsVerticalScrollIndicator: false,
7496
- scrollEventThrottle: 16,
7497
- onScroll,
7498
- children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native_reanimated14.default.View, { style: fadeFor[k], children: content })
7499
- }
7500
- ) : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native_reanimated14.default.View, { style: styles58.sectionContent, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native_reanimated14.default.View, { style: fadeFor[k], children: content }) })
7501
- ]
7502
- },
7503
- k
7504
- );
7580
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(import_react_native63.View, { style: [styles58.colBlock, { backgroundColor: bg, height }], children: [
7581
+ isDynamic && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
7582
+ import_react_native63.View,
7583
+ {
7584
+ pointerEvents: "none",
7585
+ style: styles58.measureOuter,
7586
+ onLayout: makeOnMeasure(k),
7587
+ children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: styles58.measureCopy, children: content })
7588
+ }
7589
+ ),
7590
+ scroll ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
7591
+ import_react_native63.ScrollView,
7592
+ {
7593
+ ref: innerScrollRef,
7594
+ style: styles58.innerScroll,
7595
+ showsVerticalScrollIndicator: false,
7596
+ children: content
7597
+ }
7598
+ ) : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: styles58.sectionContent, children: content })
7599
+ ] }, k);
7505
7600
  };
7506
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(AppNavigationContext.Provider, { value: navigationValue, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(import_react_native63.View, { style: [styles58.root, { backgroundColor: pageBg }], children: [
7601
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(AppLayoutDebugContext.Provider, { value: { snapshot }, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(AppNavigationContext.Provider, { value: navigationValue, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(import_react_native63.View, { style: [styles58.root, { backgroundColor: pageBg }], children: [
7507
7602
  /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
7508
- import_react_native_reanimated14.default.ScrollView,
7603
+ import_react_native63.ScrollView,
7509
7604
  {
7510
7605
  ref: scrollRef,
7511
7606
  style: styles58.pageScroll,
7512
7607
  contentContainerStyle: [styles58.pageContent, { backgroundColor: pageBg }],
7513
7608
  scrollEnabled: !!state.pageScroll,
7514
7609
  showsVerticalScrollIndicator: false,
7515
- scrollEventThrottle: 16,
7516
- onScroll,
7517
7610
  children: [
7518
7611
  renderSection("top"),
7519
7612
  showTopDivisor && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Divisor, { position: "top", handle: currentRoute.state === "top" }),
@@ -7524,7 +7617,7 @@ function AppLayout({
7524
7617
  }
7525
7618
  ),
7526
7619
  showBackButton && canGoBack && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(import_react_native63.View, { style: styles58.backBar, pointerEvents: "box-none", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Button, { variant: "secondary", size: "sm", label: "\u2190 Volver", onPress: back }) })
7527
- ] }) });
7620
+ ] }) }) });
7528
7621
  }
7529
7622
  var styles58 = import_react_native63.StyleSheet.create({
7530
7623
  root: {
@@ -7540,7 +7633,7 @@ var styles58 = import_react_native63.StyleSheet.create({
7540
7633
  width: "100%",
7541
7634
  position: "relative"
7542
7635
  },
7543
- measureCopy: {
7636
+ measureOuter: {
7544
7637
  position: "absolute",
7545
7638
  top: 0,
7546
7639
  left: 0,
@@ -7548,6 +7641,9 @@ var styles58 = import_react_native63.StyleSheet.create({
7548
7641
  opacity: 0,
7549
7642
  zIndex: -1
7550
7643
  },
7644
+ measureCopy: {
7645
+ width: "100%"
7646
+ },
7551
7647
  sectionContent: {
7552
7648
  flex: 1
7553
7649
  },
@@ -7688,6 +7784,7 @@ var import_antonella_theme59 = require("@william-callao/antonella-theme");
7688
7784
  resolveComposition,
7689
7785
  resolveTransition,
7690
7786
  updateNode,
7787
+ useAppLayoutDebug,
7691
7788
  useAppNavigation,
7692
7789
  useSheetLayout,
7693
7790
  useToast