orn-ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/README.md +9 -2
  2. package/lib/commonjs/atoms/Avatar.js +1 -1
  3. package/lib/commonjs/atoms/Avatar.js.map +1 -1
  4. package/lib/commonjs/atoms/Badge.js +10 -8
  5. package/lib/commonjs/atoms/Badge.js.map +1 -1
  6. package/lib/commonjs/atoms/Button.js +8 -6
  7. package/lib/commonjs/atoms/Button.js.map +1 -1
  8. package/lib/commonjs/atoms/Checkbox.js +4 -1
  9. package/lib/commonjs/atoms/Checkbox.js.map +1 -1
  10. package/lib/commonjs/atoms/Fab.js +1 -1
  11. package/lib/commonjs/atoms/Fab.js.map +1 -1
  12. package/lib/commonjs/atoms/Image.js +2 -2
  13. package/lib/commonjs/atoms/Image.js.map +1 -1
  14. package/lib/commonjs/atoms/Input.js +2 -2
  15. package/lib/commonjs/atoms/Input.js.map +1 -1
  16. package/lib/commonjs/atoms/PressableScale.js +9 -10
  17. package/lib/commonjs/atoms/PressableScale.js.map +1 -1
  18. package/lib/commonjs/atoms/Skeleton.js +96 -0
  19. package/lib/commonjs/atoms/Skeleton.js.map +1 -0
  20. package/lib/commonjs/atoms/Transition.js +171 -0
  21. package/lib/commonjs/atoms/Transition.js.map +1 -0
  22. package/lib/commonjs/atoms/index.js +20 -0
  23. package/lib/commonjs/atoms/index.js.map +1 -1
  24. package/lib/commonjs/molecules/AvatarHeader.js +2 -2
  25. package/lib/commonjs/molecules/AvatarHeader.js.map +1 -1
  26. package/lib/commonjs/molecules/OptionCard.js +57 -24
  27. package/lib/commonjs/molecules/OptionCard.js.map +1 -1
  28. package/lib/commonjs/molecules/{ThemeToggle.js → SegmentedControl.js} +37 -37
  29. package/lib/commonjs/molecules/SegmentedControl.js.map +1 -0
  30. package/lib/commonjs/molecules/Stepper.js +124 -47
  31. package/lib/commonjs/molecules/Stepper.js.map +1 -1
  32. package/lib/commonjs/molecules/Steps.js +2 -2
  33. package/lib/commonjs/molecules/Steps.js.map +1 -1
  34. package/lib/commonjs/molecules/index.js +9 -3
  35. package/lib/commonjs/molecules/index.js.map +1 -1
  36. package/lib/commonjs/organisms/Alert.js +6 -5
  37. package/lib/commonjs/organisms/Alert.js.map +1 -1
  38. package/lib/commonjs/organisms/AlertProvider.js +26 -0
  39. package/lib/commonjs/organisms/AlertProvider.js.map +1 -1
  40. package/lib/commonjs/organisms/BottomSheet.js +118 -39
  41. package/lib/commonjs/organisms/BottomSheet.js.map +1 -1
  42. package/lib/commonjs/organisms/DateField.js +2 -2
  43. package/lib/commonjs/organisms/DateField.js.map +1 -1
  44. package/lib/commonjs/organisms/DatePicker.js +3 -3
  45. package/lib/commonjs/organisms/DatePicker.js.map +1 -1
  46. package/lib/commonjs/organisms/List.js +66 -44
  47. package/lib/commonjs/organisms/List.js.map +1 -1
  48. package/lib/commonjs/organisms/Modal.js +42 -87
  49. package/lib/commonjs/organisms/Modal.js.map +1 -1
  50. package/lib/commonjs/organisms/NavigationBar.js +205 -0
  51. package/lib/commonjs/organisms/NavigationBar.js.map +1 -0
  52. package/lib/commonjs/organisms/Screen.js +9 -2
  53. package/lib/commonjs/organisms/Screen.js.map +1 -1
  54. package/lib/commonjs/organisms/SearchList.js +99 -30
  55. package/lib/commonjs/organisms/SearchList.js.map +1 -1
  56. package/lib/commonjs/organisms/Select.js +226 -54
  57. package/lib/commonjs/organisms/Select.js.map +1 -1
  58. package/lib/commonjs/organisms/ThemeToggle.js +52 -0
  59. package/lib/commonjs/organisms/ThemeToggle.js.map +1 -0
  60. package/lib/commonjs/organisms/Toast.js +20 -25
  61. package/lib/commonjs/organisms/Toast.js.map +1 -1
  62. package/lib/commonjs/organisms/ToastProvider.js +24 -0
  63. package/lib/commonjs/organisms/ToastProvider.js.map +1 -1
  64. package/lib/commonjs/organisms/Wizard.js +22 -2
  65. package/lib/commonjs/organisms/Wizard.js.map +1 -1
  66. package/lib/commonjs/organisms/imperativeBridge.js +28 -0
  67. package/lib/commonjs/organisms/imperativeBridge.js.map +1 -0
  68. package/lib/commonjs/organisms/index.js +50 -0
  69. package/lib/commonjs/organisms/index.js.map +1 -1
  70. package/lib/commonjs/safe-area/SafeAreaUIProvider.js +65 -0
  71. package/lib/commonjs/safe-area/SafeAreaUIProvider.js.map +1 -0
  72. package/lib/commonjs/safe-area/index.js +13 -0
  73. package/lib/commonjs/safe-area/index.js.map +1 -0
  74. package/lib/commonjs/theme/UIProvider.js +11 -0
  75. package/lib/commonjs/theme/UIProvider.js.map +1 -1
  76. package/lib/commonjs/theme/colors.js +207 -0
  77. package/lib/commonjs/theme/colors.js.map +1 -0
  78. package/lib/commonjs/theme/createTheme.js +25 -2
  79. package/lib/commonjs/theme/createTheme.js.map +1 -1
  80. package/lib/commonjs/theme/index.js +25 -0
  81. package/lib/commonjs/theme/index.js.map +1 -1
  82. package/lib/commonjs/theme/palettes.js +73 -11
  83. package/lib/commonjs/theme/palettes.js.map +1 -1
  84. package/lib/module/atoms/Avatar.js +1 -1
  85. package/lib/module/atoms/Avatar.js.map +1 -1
  86. package/lib/module/atoms/Badge.js +10 -8
  87. package/lib/module/atoms/Badge.js.map +1 -1
  88. package/lib/module/atoms/Button.js +8 -6
  89. package/lib/module/atoms/Button.js.map +1 -1
  90. package/lib/module/atoms/Checkbox.js +4 -1
  91. package/lib/module/atoms/Checkbox.js.map +1 -1
  92. package/lib/module/atoms/Fab.js +1 -1
  93. package/lib/module/atoms/Fab.js.map +1 -1
  94. package/lib/module/atoms/Image.js +2 -2
  95. package/lib/module/atoms/Image.js.map +1 -1
  96. package/lib/module/atoms/Input.js +2 -2
  97. package/lib/module/atoms/Input.js.map +1 -1
  98. package/lib/module/atoms/PressableScale.js +9 -10
  99. package/lib/module/atoms/PressableScale.js.map +1 -1
  100. package/lib/module/atoms/Skeleton.js +91 -0
  101. package/lib/module/atoms/Skeleton.js.map +1 -0
  102. package/lib/module/atoms/Transition.js +165 -0
  103. package/lib/module/atoms/Transition.js.map +1 -0
  104. package/lib/module/atoms/index.js +2 -0
  105. package/lib/module/atoms/index.js.map +1 -1
  106. package/lib/module/molecules/AvatarHeader.js +2 -2
  107. package/lib/module/molecules/AvatarHeader.js.map +1 -1
  108. package/lib/module/molecules/OptionCard.js +58 -25
  109. package/lib/module/molecules/OptionCard.js.map +1 -1
  110. package/lib/module/molecules/{ThemeToggle.js → SegmentedControl.js} +37 -37
  111. package/lib/module/molecules/SegmentedControl.js.map +1 -0
  112. package/lib/module/molecules/Stepper.js +125 -49
  113. package/lib/module/molecules/Stepper.js.map +1 -1
  114. package/lib/module/molecules/Steps.js +2 -2
  115. package/lib/module/molecules/Steps.js.map +1 -1
  116. package/lib/module/molecules/index.js +2 -2
  117. package/lib/module/molecules/index.js.map +1 -1
  118. package/lib/module/organisms/Alert.js +6 -5
  119. package/lib/module/organisms/Alert.js.map +1 -1
  120. package/lib/module/organisms/AlertProvider.js +24 -1
  121. package/lib/module/organisms/AlertProvider.js.map +1 -1
  122. package/lib/module/organisms/BottomSheet.js +120 -41
  123. package/lib/module/organisms/BottomSheet.js.map +1 -1
  124. package/lib/module/organisms/DateField.js +2 -2
  125. package/lib/module/organisms/DateField.js.map +1 -1
  126. package/lib/module/organisms/DatePicker.js +3 -3
  127. package/lib/module/organisms/DatePicker.js.map +1 -1
  128. package/lib/module/organisms/List.js +68 -46
  129. package/lib/module/organisms/List.js.map +1 -1
  130. package/lib/module/organisms/Modal.js +44 -89
  131. package/lib/module/organisms/Modal.js.map +1 -1
  132. package/lib/module/organisms/NavigationBar.js +200 -0
  133. package/lib/module/organisms/NavigationBar.js.map +1 -0
  134. package/lib/module/organisms/Screen.js +9 -2
  135. package/lib/module/organisms/Screen.js.map +1 -1
  136. package/lib/module/organisms/SearchList.js +100 -31
  137. package/lib/module/organisms/SearchList.js.map +1 -1
  138. package/lib/module/organisms/Select.js +228 -56
  139. package/lib/module/organisms/Select.js.map +1 -1
  140. package/lib/module/organisms/ThemeToggle.js +47 -0
  141. package/lib/module/organisms/ThemeToggle.js.map +1 -0
  142. package/lib/module/organisms/Toast.js +22 -27
  143. package/lib/module/organisms/Toast.js.map +1 -1
  144. package/lib/module/organisms/ToastProvider.js +21 -0
  145. package/lib/module/organisms/ToastProvider.js.map +1 -1
  146. package/lib/module/organisms/Wizard.js +23 -3
  147. package/lib/module/organisms/Wizard.js.map +1 -1
  148. package/lib/module/organisms/imperativeBridge.js +24 -0
  149. package/lib/module/organisms/imperativeBridge.js.map +1 -0
  150. package/lib/module/organisms/index.js +4 -2
  151. package/lib/module/organisms/index.js.map +1 -1
  152. package/lib/module/safe-area/SafeAreaUIProvider.js +60 -0
  153. package/lib/module/safe-area/SafeAreaUIProvider.js.map +1 -0
  154. package/lib/module/safe-area/index.js +4 -0
  155. package/lib/module/safe-area/index.js.map +1 -0
  156. package/lib/module/theme/UIProvider.js +11 -0
  157. package/lib/module/theme/UIProvider.js.map +1 -1
  158. package/lib/module/theme/colors.js +194 -0
  159. package/lib/module/theme/colors.js.map +1 -0
  160. package/lib/module/theme/createTheme.js +25 -2
  161. package/lib/module/theme/createTheme.js.map +1 -1
  162. package/lib/module/theme/index.js +1 -0
  163. package/lib/module/theme/index.js.map +1 -1
  164. package/lib/module/theme/palettes.js +73 -11
  165. package/lib/module/theme/palettes.js.map +1 -1
  166. package/lib/typescript/atoms/Badge.d.ts.map +1 -1
  167. package/lib/typescript/atoms/Button.d.ts.map +1 -1
  168. package/lib/typescript/atoms/Checkbox.d.ts.map +1 -1
  169. package/lib/typescript/atoms/PressableScale.d.ts +3 -2
  170. package/lib/typescript/atoms/PressableScale.d.ts.map +1 -1
  171. package/lib/typescript/atoms/Skeleton.d.ts +29 -0
  172. package/lib/typescript/atoms/Skeleton.d.ts.map +1 -0
  173. package/lib/typescript/atoms/Transition.d.ts +51 -0
  174. package/lib/typescript/atoms/Transition.d.ts.map +1 -0
  175. package/lib/typescript/atoms/index.d.ts +4 -0
  176. package/lib/typescript/atoms/index.d.ts.map +1 -1
  177. package/lib/typescript/molecules/OptionCard.d.ts +11 -6
  178. package/lib/typescript/molecules/OptionCard.d.ts.map +1 -1
  179. package/lib/typescript/molecules/SegmentedControl.d.ts +24 -0
  180. package/lib/typescript/molecules/SegmentedControl.d.ts.map +1 -0
  181. package/lib/typescript/molecules/Stepper.d.ts +35 -3
  182. package/lib/typescript/molecules/Stepper.d.ts.map +1 -1
  183. package/lib/typescript/molecules/index.d.ts +4 -4
  184. package/lib/typescript/molecules/index.d.ts.map +1 -1
  185. package/lib/typescript/organisms/Alert.d.ts.map +1 -1
  186. package/lib/typescript/organisms/AlertProvider.d.ts +9 -0
  187. package/lib/typescript/organisms/AlertProvider.d.ts.map +1 -1
  188. package/lib/typescript/organisms/BottomSheet.d.ts +26 -4
  189. package/lib/typescript/organisms/BottomSheet.d.ts.map +1 -1
  190. package/lib/typescript/organisms/List.d.ts +9 -2
  191. package/lib/typescript/organisms/List.d.ts.map +1 -1
  192. package/lib/typescript/organisms/Modal.d.ts +3 -5
  193. package/lib/typescript/organisms/Modal.d.ts.map +1 -1
  194. package/lib/typescript/organisms/NavigationBar.d.ts +32 -0
  195. package/lib/typescript/organisms/NavigationBar.d.ts.map +1 -0
  196. package/lib/typescript/organisms/Screen.d.ts +2 -1
  197. package/lib/typescript/organisms/Screen.d.ts.map +1 -1
  198. package/lib/typescript/organisms/SearchList.d.ts +21 -5
  199. package/lib/typescript/organisms/SearchList.d.ts.map +1 -1
  200. package/lib/typescript/organisms/Select.d.ts +19 -4
  201. package/lib/typescript/organisms/Select.d.ts.map +1 -1
  202. package/lib/typescript/{molecules → organisms}/ThemeToggle.d.ts +4 -4
  203. package/lib/typescript/organisms/ThemeToggle.d.ts.map +1 -0
  204. package/lib/typescript/organisms/Toast.d.ts.map +1 -1
  205. package/lib/typescript/organisms/ToastProvider.d.ts +8 -0
  206. package/lib/typescript/organisms/ToastProvider.d.ts.map +1 -1
  207. package/lib/typescript/organisms/Wizard.d.ts +7 -1
  208. package/lib/typescript/organisms/Wizard.d.ts.map +1 -1
  209. package/lib/typescript/organisms/imperativeBridge.d.ts +12 -0
  210. package/lib/typescript/organisms/imperativeBridge.d.ts.map +1 -0
  211. package/lib/typescript/organisms/index.d.ts +7 -3
  212. package/lib/typescript/organisms/index.d.ts.map +1 -1
  213. package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts +46 -0
  214. package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts.map +1 -0
  215. package/lib/typescript/safe-area/index.d.ts +3 -0
  216. package/lib/typescript/safe-area/index.d.ts.map +1 -0
  217. package/lib/typescript/theme/UIProvider.d.ts.map +1 -1
  218. package/lib/typescript/theme/colors.d.ts +44 -0
  219. package/lib/typescript/theme/colors.d.ts.map +1 -0
  220. package/lib/typescript/theme/createTheme.d.ts +3 -0
  221. package/lib/typescript/theme/createTheme.d.ts.map +1 -1
  222. package/lib/typescript/theme/index.d.ts +3 -1
  223. package/lib/typescript/theme/index.d.ts.map +1 -1
  224. package/lib/typescript/theme/palettes.d.ts +41 -3
  225. package/lib/typescript/theme/palettes.d.ts.map +1 -1
  226. package/lib/typescript/theme/types.d.ts +9 -0
  227. package/lib/typescript/theme/types.d.ts.map +1 -1
  228. package/package.json +101 -18
  229. package/registry/alert-provider.json +9 -2
  230. package/registry/alert.json +1 -1
  231. package/registry/avatar-header.json +1 -1
  232. package/registry/avatar.json +1 -1
  233. package/registry/badge.json +1 -1
  234. package/registry/bottom-sheet.json +6 -2
  235. package/registry/button.json +1 -1
  236. package/registry/checkbox.json +1 -1
  237. package/registry/core.json +9 -5
  238. package/registry/date-field.json +2 -1
  239. package/registry/date-picker.json +1 -1
  240. package/registry/fab.json +1 -1
  241. package/registry/image.json +1 -1
  242. package/registry/index.json +108 -39
  243. package/registry/input.json +1 -1
  244. package/registry/list.json +2 -1
  245. package/registry/manifest.json +44 -6
  246. package/registry/modal.json +3 -2
  247. package/registry/navigation-bar.json +18 -0
  248. package/registry/option-card.json +3 -2
  249. package/registry/pressable-scale.json +1 -1
  250. package/registry/screen.json +1 -1
  251. package/registry/search-list.json +2 -1
  252. package/registry/segmented-control.json +18 -0
  253. package/registry/select.json +1 -1
  254. package/registry/skeleton.json +18 -0
  255. package/registry/stepper.json +3 -2
  256. package/registry/steps.json +1 -1
  257. package/registry/theme-toggle.json +5 -4
  258. package/registry/toast-provider.json +11 -3
  259. package/registry/toast.json +3 -2
  260. package/registry/transition.json +19 -0
  261. package/registry/wizard.json +3 -2
  262. package/src/atoms/Avatar.tsx +1 -1
  263. package/src/atoms/Badge.tsx +6 -4
  264. package/src/atoms/Button.tsx +8 -6
  265. package/src/atoms/Checkbox.tsx +4 -1
  266. package/src/atoms/Fab.tsx +1 -1
  267. package/src/atoms/Image.tsx +2 -2
  268. package/src/atoms/Input.tsx +2 -2
  269. package/src/atoms/PressableScale.tsx +16 -6
  270. package/src/atoms/Skeleton.tsx +114 -0
  271. package/src/atoms/Transition.tsx +189 -0
  272. package/src/atoms/index.ts +4 -0
  273. package/src/molecules/AvatarHeader.tsx +2 -2
  274. package/src/molecules/OptionCard.tsx +64 -27
  275. package/src/molecules/SegmentedControl.tsx +84 -0
  276. package/src/molecules/Stepper.tsx +147 -32
  277. package/src/molecules/Steps.tsx +2 -2
  278. package/src/molecules/index.ts +4 -4
  279. package/src/organisms/Alert.tsx +6 -5
  280. package/src/organisms/AlertProvider.tsx +26 -1
  281. package/src/organisms/BottomSheet.tsx +214 -62
  282. package/src/organisms/DateField.tsx +2 -2
  283. package/src/organisms/DatePicker.tsx +3 -3
  284. package/src/organisms/List.tsx +73 -41
  285. package/src/organisms/Modal.tsx +49 -61
  286. package/src/organisms/NavigationBar.tsx +223 -0
  287. package/src/organisms/Screen.tsx +11 -3
  288. package/src/organisms/SearchList.tsx +134 -38
  289. package/src/organisms/Select.tsx +227 -49
  290. package/src/organisms/ThemeToggle.tsx +30 -0
  291. package/src/organisms/Toast.tsx +19 -24
  292. package/src/organisms/ToastProvider.tsx +24 -0
  293. package/src/organisms/Wizard.tsx +36 -3
  294. package/src/organisms/imperativeBridge.ts +28 -0
  295. package/src/organisms/index.ts +7 -3
  296. package/src/safe-area/SafeAreaUIProvider.tsx +67 -0
  297. package/src/safe-area/index.ts +2 -0
  298. package/src/theme/UIProvider.tsx +15 -0
  299. package/src/theme/colors.ts +175 -0
  300. package/src/theme/createTheme.ts +38 -4
  301. package/src/theme/index.ts +3 -1
  302. package/src/theme/palettes.ts +108 -11
  303. package/src/theme/types.ts +10 -0
  304. package/lib/commonjs/molecules/ThemeToggle.js.map +0 -1
  305. package/lib/module/molecules/ThemeToggle.js.map +0 -1
  306. package/lib/typescript/molecules/ThemeToggle.d.ts.map +0 -1
  307. package/src/molecules/ThemeToggle.tsx +0 -67
@@ -1,7 +1,8 @@
1
- import React, { memo, useEffect, useRef } from 'react';
2
- import { Animated, Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';
1
+ import React, { memo } from 'react';
2
+ import { Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';
3
3
  import { createStyles } from '../theme/createStyles';
4
4
  import { useAllowFontScaling, useColors } from '../theme/UIProvider';
5
+ import { Transition } from '../atoms/Transition';
5
6
  import { Icon } from '../icons/Icon';
6
7
  import type { IconName } from '../icons/types';
7
8
 
@@ -70,17 +71,25 @@ export const Toast = memo(
70
71
  const styles = useStyles();
71
72
  const allowFontScaling = useAllowFontScaling();
72
73
 
73
- const accentColor: Record<ToastVariant, string> = {
74
+ // La barra lateral es relleno (acento pleno); el ícono es contenido
75
+ // sobre la superficie del toast y necesita el rol `*Text`.
76
+ const barColor: Record<ToastVariant, string> = {
74
77
  success: colors.success,
75
78
  error: colors.error,
76
79
  warning: colors.warning,
77
80
  info: colors.secondary,
78
81
  };
82
+ const iconColor: Record<ToastVariant, string> = {
83
+ success: colors.successText,
84
+ error: colors.errorText,
85
+ warning: colors.warningText,
86
+ info: colors.secondaryText,
87
+ };
79
88
 
80
89
  const body = (
81
90
  <View style={[styles.container, style]} testID={testID} accessibilityRole="alert">
82
- <View style={[styles.accent, { backgroundColor: accentColor[variant] }]} />
83
- <Icon name={ICON_BY_VARIANT[variant]} size={22} color={accentColor[variant]} />
91
+ <View style={[styles.accent, { backgroundColor: barColor[variant] }]} />
92
+ <Icon name={ICON_BY_VARIANT[variant]} size={22} color={iconColor[variant]} />
84
93
  <View style={styles.text}>
85
94
  <Text allowFontScaling={allowFontScaling} style={styles.title}>
86
95
  {title}
@@ -112,24 +121,10 @@ Toast.displayName = 'Toast';
112
121
 
113
122
  /** Envuelve un Toast con su animación de entrada/salida. Uso interno del provider. */
114
123
  export const AnimatedToast = memo(
115
- ({ children, onHeight }: { children: React.ReactNode; onHeight?: (h: number) => void }) => {
116
- const progress = useRef(new Animated.Value(0)).current;
117
-
118
- useEffect(() => {
119
- Animated.spring(progress, { toValue: 1, useNativeDriver: true, speed: 14, bounciness: 4 }).start();
120
- }, [progress]);
121
-
122
- return (
123
- <Animated.View
124
- onLayout={(e) => onHeight?.(e.nativeEvent.layout.height)}
125
- style={{
126
- opacity: progress,
127
- transform: [{ translateY: progress.interpolate({ inputRange: [0, 1], outputRange: [-16, 0] }) }],
128
- }}
129
- >
130
- {children}
131
- </Animated.View>
132
- );
133
- }
124
+ ({ children, onHeight }: { children: React.ReactNode; onHeight?: (h: number) => void }) => (
125
+ <Transition preset={['fade', 'slide-down']} distance={16} spring>
126
+ <View onLayout={(e) => onHeight?.(e.nativeEvent.layout.height)}>{children}</View>
127
+ </Transition>
128
+ )
134
129
  );
135
130
  AnimatedToast.displayName = 'AnimatedToast';
@@ -3,6 +3,7 @@ import { View } from 'react-native';
3
3
  import { AnimatedToast, Toast, type ToastVariant } from './Toast';
4
4
  import { useInsets } from '../theme/UIProvider';
5
5
  import { createStyles } from '../theme/createStyles';
6
+ import { createImperativeBridge } from './imperativeBridge';
6
7
 
7
8
  export interface ToastOptions {
8
9
  title: string;
@@ -26,6 +27,24 @@ interface ToastContextValue {
26
27
  }
27
28
 
28
29
  const ToastContext = createContext<ToastContextValue | undefined>(undefined);
30
+ const bridge = createImperativeBridge<ToastContextValue>('ToastProvider');
31
+
32
+ /**
33
+ * Muestra un toast desde fuera del árbol de React —un servicio, un
34
+ * interceptor— sin pasar por el hook. Devuelve el id, o '' si no hay
35
+ * <ToastProvider> montado.
36
+ */
37
+ export function showToast(options: ToastOptions): string {
38
+ return bridge.get()?.show(options) ?? '';
39
+ }
40
+
41
+ export function hideToast(id: string): void {
42
+ bridge.get()?.hide(id);
43
+ }
44
+
45
+ export function hideAllToasts(): void {
46
+ bridge.get()?.hideAll();
47
+ }
29
48
 
30
49
  const useStyles = createStyles((theme) => ({
31
50
  host: { position: 'absolute', left: 0, right: 0, paddingHorizontal: theme.tokens.spacing.lg, gap: theme.tokens.spacing.sm },
@@ -122,6 +141,11 @@ export function ToastProvider({
122
141
 
123
142
  const value = useMemo<ToastContextValue>(() => ({ show, hide, hideAll }), [show, hide, hideAll]);
124
143
 
144
+ useEffect(() => {
145
+ bridge.set(value);
146
+ return () => bridge.set(null);
147
+ }, [value]);
148
+
125
149
  const hostPosition =
126
150
  position === 'top'
127
151
  ? { top: insets.top + 8 }
@@ -1,8 +1,9 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { ScrollView, View, type StyleProp, type ViewStyle } from 'react-native';
3
3
  import { createStyles } from '../theme/createStyles';
4
4
  import { Steps, type StepItem } from '../molecules/Steps';
5
5
  import { Button } from '../atoms/Button';
6
+ import { Transition } from '../atoms/Transition';
6
7
 
7
8
  export interface WizardStep extends StepItem {
8
9
  content: React.ReactNode;
@@ -31,6 +32,12 @@ export interface WizardProps {
31
32
  * @default true
32
33
  */
33
34
  scrollableContent?: boolean;
35
+ /**
36
+ * El contenido del paso entra deslizándose en el sentido de la navegación.
37
+ * Sólo opacity y transform, así que la animación corre en el hilo nativo.
38
+ * @default true
39
+ */
40
+ animated?: boolean;
34
41
  style?: StyleProp<ViewStyle>;
35
42
  }
36
43
 
@@ -61,6 +68,7 @@ export function Wizard({
61
68
  nextLabel = 'Next',
62
69
  finishLabel = 'Finish',
63
70
  scrollableContent = true,
71
+ animated = true,
64
72
  style,
65
73
  }: WizardProps) {
66
74
  const styles = useStyles();
@@ -82,6 +90,15 @@ export function Wizard({
82
90
  [steps]
83
91
  );
84
92
 
93
+ // El ref todavía guarda el paso anterior durante el render que trae el nuevo.
94
+ const previous = useRef(current);
95
+ const forward = current >= previous.current;
96
+ const entered = useRef(false);
97
+ useEffect(() => {
98
+ previous.current = current;
99
+ entered.current = true;
100
+ }, [current]);
101
+
85
102
  const activeStep = steps[current];
86
103
  const isFirst = current === 0;
87
104
  const isLast = current === steps.length - 1;
@@ -92,6 +109,22 @@ export function Wizard({
92
109
  else goTo(current + 1);
93
110
  };
94
111
 
112
+ // El paso saliente no se anima: mantener los dos montados a la vez duplicaría
113
+ // los formularios y su estado.
114
+ const renderContent = () =>
115
+ animated ? (
116
+ <Transition
117
+ key={current}
118
+ testID="wizard-step"
119
+ preset={['fade', forward ? 'slide-left' : 'slide-right']}
120
+ appear={entered.current}
121
+ >
122
+ {activeStep?.content}
123
+ </Transition>
124
+ ) : (
125
+ activeStep?.content
126
+ );
127
+
95
128
  return (
96
129
  <View style={[styles.container, style]}>
97
130
  <Steps
@@ -115,10 +148,10 @@ export function Wizard({
115
148
  automaticallyAdjustKeyboardInsets
116
149
  showsVerticalScrollIndicator={false}
117
150
  >
118
- {activeStep?.content}
151
+ {renderContent()}
119
152
  </ScrollView>
120
153
  ) : (
121
- <View style={styles.content}>{activeStep?.content}</View>
154
+ <View style={styles.content}>{renderContent()}</View>
122
155
  )}
123
156
 
124
157
  <View style={styles.footer}>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Puente entre el proveedor montado y el código que no es un componente
3
+ * (servicios, capa de API, interceptores). El proveedor se registra al montar y
4
+ * se borra al desmontar, así que fuera del árbol nunca queda una referencia
5
+ * viva a un contexto muerto.
6
+ */
7
+ export interface ImperativeBridge<T> {
8
+ set: (value: T | null) => void;
9
+ get: () => T | null;
10
+ }
11
+
12
+ export function createImperativeBridge<T>(providerName: string): ImperativeBridge<T> {
13
+ let current: T | null = null;
14
+
15
+ return {
16
+ set: (value) => {
17
+ current = value;
18
+ },
19
+ get: () => {
20
+ if (!current && __DEV__) {
21
+ console.warn(
22
+ `orn-ui: se llamó a la API imperativa sin un <${providerName}> montado. La llamada se ignoró.`
23
+ );
24
+ }
25
+ return current;
26
+ },
27
+ };
28
+ }
@@ -1,12 +1,12 @@
1
1
  export { Modal } from './Modal';
2
2
  export type { ModalProps, ModalVariant } from './Modal';
3
3
  export { BottomSheet } from './BottomSheet';
4
- export type { BottomSheetProps } from './BottomSheet';
4
+ export type { BottomSheetProps, FooterPlacement } from './BottomSheet';
5
5
  export { Select } from './Select';
6
6
  export type { SelectProps, SelectOption } from './Select';
7
7
  export { Alert } from './Alert';
8
8
  export type { AlertProps, AlertButton, AlertType } from './Alert';
9
- export { AlertProvider, useAlert } from './AlertProvider';
9
+ export { AlertProvider, useAlert, showAlert, showConfirm, hideAlert } from './AlertProvider';
10
10
  export type { AlertOptions, ConfirmOptions } from './AlertProvider';
11
11
  export { Screen } from './Screen';
12
12
  export type { ScreenProps, ScreenEdge } from './Screen';
@@ -16,7 +16,7 @@ export { SearchList } from './SearchList';
16
16
  export type { SearchListProps } from './SearchList';
17
17
  export { Toast } from './Toast';
18
18
  export type { ToastProps, ToastVariant } from './Toast';
19
- export { ToastProvider, useToast } from './ToastProvider';
19
+ export { ToastProvider, useToast, showToast, hideToast, hideAllToasts } from './ToastProvider';
20
20
  export type { ToastProviderProps, ToastOptions } from './ToastProvider';
21
21
  export { DatePicker, buildMonthGrid, DEFAULT_MONTH_NAMES, DEFAULT_WEEKDAY_NAMES } from './DatePicker';
22
22
  export type { DatePickerProps, DateRange } from './DatePicker';
@@ -24,3 +24,7 @@ export { DateField } from './DateField';
24
24
  export type { DateFieldProps } from './DateField';
25
25
  export { Wizard } from './Wizard';
26
26
  export type { WizardProps, WizardStep } from './Wizard';
27
+ export { ThemeToggle } from './ThemeToggle';
28
+ export type { ThemeToggleProps } from './ThemeToggle';
29
+ export { NavigationBar } from './NavigationBar';
30
+ export type { NavigationBarProps, NavigationBarItem } from './NavigationBar';
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
3
+ import { UIProvider, type UIProviderProps } from '../theme/UIProvider';
4
+
5
+ export interface SafeAreaUIProviderProps extends Omit<UIProviderProps, 'insets'> {
6
+ /**
7
+ * Insets explícitos. Ganan sobre los medidos — útil para tests, storybook o
8
+ * una pantalla embebida que no ocupa la ventana entera.
9
+ */
10
+ insets?: UIProviderProps['insets'];
11
+ /**
12
+ * Montar también el `<SafeAreaProvider>`. Ponelo en false si tu app ya tiene
13
+ * uno arriba (React Navigation lo monta solo en algunas plantillas):
14
+ * un provider anidado mide el frame de *su* View, no el de la ventana, así
15
+ * que ahí adentro los insets darían cero.
16
+ * @default true
17
+ */
18
+ mountSafeAreaProvider?: boolean;
19
+ }
20
+
21
+ function Measured({ insets: override, children, ...rest }: SafeAreaUIProviderProps) {
22
+ const measured = useSafeAreaInsets();
23
+ return (
24
+ <UIProvider insets={override ?? measured} {...rest}>
25
+ {children}
26
+ </UIProvider>
27
+ );
28
+ }
29
+
30
+ /**
31
+ * SafeAreaUIProvider
32
+ * `UIProvider` con los insets ya cableados desde `react-native-safe-area-context`.
33
+ *
34
+ * Vive en su propio subpath (`orn-ui/safe-area`) a propósito: es el único
35
+ * archivo de la librería que importa un paquete de terceros. Nada del entry
36
+ * principal lo referencia, así que quien hace `import { Button } from 'orn-ui'`
37
+ * nunca lo resuelve y el bundle sigue sin dependencias de runtime.
38
+ *
39
+ * ```tsx
40
+ * import { SafeAreaUIProvider } from 'orn-ui/safe-area';
41
+ *
42
+ * export default function App() {
43
+ * return (
44
+ * <SafeAreaUIProvider defaultMode="system">
45
+ * <RootNavigator />
46
+ * </SafeAreaUIProvider>
47
+ * );
48
+ * }
49
+ * ```
50
+ *
51
+ * El equivalente a mano — pasarle `insets={useSafeAreaInsets()}` a `UIProvider`
52
+ * desde un componente que ya esté dentro de `<SafeAreaProvider>` — sigue
53
+ * siendo válido. Esto sólo evita el error silencioso de olvidarlo: `insets`
54
+ * por defecto es `{0,0,0,0}`, y con ceros el bottom sheet queda pegado contra
55
+ * la barra de gestos y el modal `full` se mete abajo del notch.
56
+ */
57
+ export function SafeAreaUIProvider({
58
+ mountSafeAreaProvider = true,
59
+ ...props
60
+ }: SafeAreaUIProviderProps) {
61
+ if (!mountSafeAreaProvider) return <Measured {...props} />;
62
+ return (
63
+ <SafeAreaProvider>
64
+ <Measured {...props} />
65
+ </SafeAreaProvider>
66
+ );
67
+ }
@@ -0,0 +1,2 @@
1
+ export { SafeAreaUIProvider } from './SafeAreaUIProvider';
2
+ export type { SafeAreaUIProviderProps } from './SafeAreaUIProvider';
@@ -21,6 +21,9 @@ interface UIContextValue {
21
21
 
22
22
  const UIContext = createContext<UIContextValue | undefined>(undefined);
23
23
 
24
+ /** Una sola vez por sesión: en un re-render el aviso no aporta nada nuevo. */
25
+ let warnedAboutInsets = false;
26
+
24
27
  export interface UIProviderProps {
25
28
  children: React.ReactNode;
26
29
  /** Par light/dark. Por defecto el theme de marca de la librería (créalo con createTheme()). */
@@ -70,6 +73,18 @@ export function UIProvider({
70
73
  [isControlled, onModeChange]
71
74
  );
72
75
 
76
+ // Olvidar `insets` no rompe nada visible al montar: el default de ceros
77
+ // recién se nota cuando abrís un Modal `full` (se mete abajo del notch) o un
78
+ // BottomSheet (queda pegado a la barra de gestos). El aviso llega antes.
79
+ if (__DEV__ && insets === zeroInsets && !warnedAboutInsets) {
80
+ warnedAboutInsets = true;
81
+ console.warn(
82
+ 'orn-ui: <UIProvider> sin `insets`, se usan {top:0,bottom:0,left:0,right:0}. ' +
83
+ 'Los modales y el Screen quedan sin safe area. Pasá `insets={useSafeAreaInsets()}` ' +
84
+ "o usá <SafeAreaUIProvider> de 'orn-ui/safe-area', que lo cablea solo."
85
+ );
86
+ }
87
+
73
88
  const scheme: 'light' | 'dark' =
74
89
  mode === 'system' ? (systemScheme === 'dark' ? 'dark' : 'light') : mode;
75
90
 
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Utilidades de color sin dependencias, usadas para derivar una familia de
3
+ * roles (relleno / encima / tenue / legible) a partir de un solo hex de marca.
4
+ */
5
+
6
+ /** Contraste mínimo AA para texto normal. */
7
+ export const AA_CONTRAST = 4.5;
8
+
9
+ export interface Rgb {
10
+ r: number;
11
+ g: number;
12
+ b: number;
13
+ }
14
+
15
+ export interface Hsl {
16
+ h: number;
17
+ s: number;
18
+ l: number;
19
+ }
20
+
21
+ /** Roles que necesita un acento del theme, en un esquema concreto. */
22
+ export interface AccentRoles {
23
+ /** Relleno pleno: fondo de botón, círculo del paso actual. */
24
+ base: string;
25
+ /** Texto/ícono que va encima del relleno. */
26
+ on: string;
27
+ /** Fondo tenue: badges, pill del indicador activo. */
28
+ soft: string;
29
+ /** El acento legible sobre `surface`: labels, links. */
30
+ text: string;
31
+ }
32
+
33
+ const HEX = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;
34
+
35
+ export function hexToRgb(hex: string): Rgb {
36
+ const match = HEX.exec(hex.trim());
37
+ if (!match) {
38
+ throw new Error(`orn-ui: se esperaba un color hex como "#7c3aed", se recibió "${hex}".`);
39
+ }
40
+ const digits = match[1]!;
41
+ const full = digits.length === 3 ? digits.replace(/./g, (c) => c + c) : digits;
42
+ return {
43
+ r: parseInt(full.slice(0, 2), 16),
44
+ g: parseInt(full.slice(2, 4), 16),
45
+ b: parseInt(full.slice(4, 6), 16),
46
+ };
47
+ }
48
+
49
+ const toHexPair = (value: number) => Math.round(clamp(value, 0, 255)).toString(16).padStart(2, '0');
50
+
51
+ export function rgbToHex({ r, g, b }: Rgb): string {
52
+ return `#${toHexPair(r)}${toHexPair(g)}${toHexPair(b)}`;
53
+ }
54
+
55
+ function clamp(value: number, min: number, max: number) {
56
+ return Math.min(max, Math.max(min, value));
57
+ }
58
+
59
+ export function rgbToHsl({ r, g, b }: Rgb): Hsl {
60
+ const rn = r / 255;
61
+ const gn = g / 255;
62
+ const bn = b / 255;
63
+ const max = Math.max(rn, gn, bn);
64
+ const min = Math.min(rn, gn, bn);
65
+ const delta = max - min;
66
+ const l = (max + min) / 2;
67
+
68
+ if (delta === 0) return { h: 0, s: 0, l };
69
+
70
+ const s = delta / (1 - Math.abs(2 * l - 1));
71
+ let h: number;
72
+ if (max === rn) h = ((gn - bn) / delta) % 6;
73
+ else if (max === gn) h = (bn - rn) / delta + 2;
74
+ else h = (rn - gn) / delta + 4;
75
+
76
+ h *= 60;
77
+ return { h: h < 0 ? h + 360 : h, s, l };
78
+ }
79
+
80
+ export function hslToRgb({ h, s, l }: Hsl): Rgb {
81
+ const c = (1 - Math.abs(2 * l - 1)) * s;
82
+ const hp = (((h % 360) + 360) % 360) / 60;
83
+ const x = c * (1 - Math.abs((hp % 2) - 1));
84
+ const [r1, g1, b1] =
85
+ hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x] : hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
86
+ const m = l - c / 2;
87
+ return { r: (r1 + m) * 255, g: (g1 + m) * 255, b: (b1 + m) * 255 };
88
+ }
89
+
90
+ export function toHsl(hex: string): Hsl {
91
+ return rgbToHsl(hexToRgb(hex));
92
+ }
93
+
94
+ export function toHex(hsl: Hsl): string {
95
+ return rgbToHex(hslToRgb({ ...hsl, s: clamp(hsl.s, 0, 1), l: clamp(hsl.l, 0, 1) }));
96
+ }
97
+
98
+ function channelLuminance(value: number) {
99
+ const c = value / 255;
100
+ return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
101
+ }
102
+
103
+ /** Luminancia relativa WCAG de un hex. */
104
+ export function luminance(hex: string): number {
105
+ const { r, g, b } = hexToRgb(hex);
106
+ return 0.2126 * channelLuminance(r) + 0.7152 * channelLuminance(g) + 0.0722 * channelLuminance(b);
107
+ }
108
+
109
+ /** Ratio de contraste WCAG entre dos hex: 1 (igual) a 21 (blanco sobre negro). */
110
+ export function contrast(a: string, b: string): number {
111
+ const la = luminance(a);
112
+ const lb = luminance(b);
113
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
114
+ }
115
+
116
+ /**
117
+ * Blanco si alcanza el contraste AA —es lo que se espera encima de un relleno
118
+ * de color— y si no, el extremo que más contraste dé.
119
+ */
120
+ function bestOnColor(background: string, light: string, dark: string): string {
121
+ if (contrast(background, light) >= AA_CONTRAST) return light;
122
+ return contrast(background, dark) >= contrast(background, light) ? dark : light;
123
+ }
124
+
125
+ /**
126
+ * Mueve la luminosidad del tono hasta alcanzar el contraste pedido contra
127
+ * `against`. Si ni el extremo llega —un amarillo puro sobre blanco, por
128
+ * ejemplo— devuelve el más contrastado que encontró en el camino.
129
+ */
130
+ function reachContrast(hsl: Hsl, against: string, target: number, direction: 'darker' | 'lighter'): string {
131
+ const step = direction === 'darker' ? -0.02 : 0.02;
132
+ let best = toHex(hsl);
133
+ let bestRatio = contrast(best, against);
134
+
135
+ for (let l = hsl.l; l >= 0 && l <= 1; l += step) {
136
+ const candidate = toHex({ ...hsl, l });
137
+ const ratio = contrast(candidate, against);
138
+ if (ratio > bestRatio) {
139
+ best = candidate;
140
+ bestRatio = ratio;
141
+ }
142
+ if (ratio >= target) return candidate;
143
+ }
144
+
145
+ return best;
146
+ }
147
+
148
+ /**
149
+ * Deriva los cuatro roles de un acento a partir de un hex, para un esquema.
150
+ * `surface` es el fondo sobre el que tiene que leerse el rol `text`, así que
151
+ * cada esquema pasa el suyo.
152
+ */
153
+ export function deriveAccent(hex: string, scheme: 'light' | 'dark', surface: string): AccentRoles {
154
+ const hsl = toHsl(hex);
155
+
156
+ if (scheme === 'light') {
157
+ const base = toHex(hsl);
158
+ return {
159
+ base,
160
+ on: bestOnColor(base, '#ffffff', '#1a1a1a'),
161
+ soft: toHex({ h: hsl.h, s: Math.min(hsl.s, 0.85), l: 0.94 }),
162
+ text: reachContrast({ ...hsl, l: Math.min(hsl.l, 0.38) }, surface, AA_CONTRAST, 'darker'),
163
+ };
164
+ }
165
+
166
+ // En oscuro el acento sube de luminosidad y lo que va encima baja: un
167
+ // #004cef sobre #1e1e1e no se distingue del fondo.
168
+ const base = toHex({ ...hsl, l: 0.72 });
169
+ return {
170
+ base,
171
+ on: bestOnColor(base, '#ffffff', toHex({ ...hsl, s: Math.min(hsl.s, 0.9), l: 0.16 })),
172
+ soft: toHex({ h: hsl.h, s: Math.min(hsl.s, 0.35), l: 0.18 }),
173
+ text: reachContrast({ ...hsl, l: Math.max(hsl.l, 0.74) }, surface, AA_CONTRAST, 'lighter'),
174
+ };
175
+ }
@@ -1,6 +1,7 @@
1
- import { lightPalette, darkPalette } from './palettes';
1
+ import { lightPalette, darkPalette, type ThemeColors } from './palettes';
2
2
  import { tokens as defaultTokens } from './tokens';
3
- import type { Theme, ThemeOverrides, ThemePair } from './types';
3
+ import { deriveAccent } from './colors';
4
+ import type { BrandAccent, Theme, ThemeOverrides, ThemePair } from './types';
4
5
 
5
6
  function mergeDeep<T extends Record<string, any>>(base: T, patch?: Partial<T>): T {
6
7
  if (!patch) return base;
@@ -23,22 +24,55 @@ function mergeDeep<T extends Record<string, any>>(base: T, patch?: Partial<T>):
23
24
  return out as T;
24
25
  }
25
26
 
27
+ const capitalize = <T extends string>(name: T) => (name.charAt(0).toUpperCase() + name.slice(1)) as Capitalize<T>;
28
+
29
+ /** Expande cada hex de `brand` a los cuatro roles del acento en un esquema. */
30
+ function brandColors(
31
+ brand: ThemeOverrides['brand'],
32
+ scheme: 'light' | 'dark',
33
+ palette: ThemeColors
34
+ ): Partial<ThemeColors> {
35
+ if (!brand) return {};
36
+ const accents = typeof brand === 'string' ? { primary: brand } : brand;
37
+ const out: Partial<ThemeColors> = {};
38
+
39
+ for (const [name, hex] of Object.entries(accents) as [BrandAccent, string | undefined][]) {
40
+ if (!hex) continue;
41
+ const roles = deriveAccent(hex, scheme, palette.surface);
42
+ out[name] = roles.base;
43
+ out[`on${capitalize(name)}`] = roles.on;
44
+ out[`${name}Soft`] = roles.soft;
45
+ out[`${name}Text`] = roles.text;
46
+ }
47
+
48
+ return out;
49
+ }
50
+
26
51
  /**
27
52
  * Construye el par de themes light/dark que consume <UIProvider theme={...}>.
28
53
  * Nunca muta los defaults: cada llamada produce objetos nuevos, seguros de
29
54
  * compartir entre providers distintos (tests, multi-brand en el mismo árbol).
55
+ *
56
+ * `brand` se aplica antes que `colors`, así que un rol escrito a mano siempre
57
+ * gana sobre el derivado.
30
58
  */
31
59
  export function createTheme(overrides?: ThemeOverrides): ThemePair {
32
60
  const tokens = mergeDeep(defaultTokens, overrides?.tokens as any);
33
61
 
34
62
  const light: Theme = {
35
- colors: mergeDeep(lightPalette, overrides?.colors?.light),
63
+ colors: mergeDeep(
64
+ mergeDeep(lightPalette, brandColors(overrides?.brand, 'light', lightPalette)),
65
+ overrides?.colors?.light
66
+ ),
36
67
  tokens,
37
68
  scheme: 'light',
38
69
  };
39
70
 
40
71
  const dark: Theme = {
41
- colors: mergeDeep(darkPalette, overrides?.colors?.dark),
72
+ colors: mergeDeep(
73
+ mergeDeep(darkPalette, brandColors(overrides?.brand, 'dark', darkPalette)),
74
+ overrides?.colors?.dark
75
+ ),
42
76
  tokens,
43
77
  scheme: 'dark',
44
78
  };
@@ -3,7 +3,9 @@ export type { Tokens } from './tokens';
3
3
  export { lightPalette, darkPalette } from './palettes';
4
4
  export type { ThemeColors } from './palettes';
5
5
  export { createTheme, defaultTheme } from './createTheme';
6
- export type { Theme, ThemePair, ThemeOverrides, DeepPartial } from './types';
6
+ export type { Theme, ThemePair, ThemeOverrides, BrandAccent, DeepPartial } from './types';
7
+ export { deriveAccent, contrast, luminance, AA_CONTRAST } from './colors';
8
+ export type { AccentRoles } from './colors';
7
9
  export { defaultLabels } from './labels';
8
10
  export type { Labels } from './labels';
9
11
  export { zeroInsets } from './insets';