@webority-technologies/mobile 0.0.14 → 0.0.20

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 (202) hide show
  1. package/lib/commonjs/components/Accordion/Accordion.js +60 -19
  2. package/lib/commonjs/components/AppBar/AppBar.js +29 -20
  3. package/lib/commonjs/components/Avatar/Avatar.js +38 -8
  4. package/lib/commonjs/components/Badge/Badge.js +66 -4
  5. package/lib/commonjs/components/Banner/Banner.js +146 -66
  6. package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +37 -15
  7. package/lib/commonjs/components/BottomSheet/BottomSheet.js +85 -50
  8. package/lib/commonjs/components/Button/Button.js +12 -5
  9. package/lib/commonjs/components/Card/Card.js +106 -16
  10. package/lib/commonjs/components/Carousel/Carousel.js +66 -12
  11. package/lib/commonjs/components/Checkbox/Checkbox.js +11 -7
  12. package/lib/commonjs/components/Chip/Chip.js +44 -12
  13. package/lib/commonjs/components/DatePicker/DatePicker.js +185 -76
  14. package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +133 -59
  15. package/lib/commonjs/components/Dialog/Dialog.js +16 -10
  16. package/lib/commonjs/components/Drawer/Drawer.js +13 -10
  17. package/lib/commonjs/components/FieldBase/FieldBase.js +306 -0
  18. package/lib/commonjs/components/FieldBase/index.js +32 -0
  19. package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +69 -44
  20. package/lib/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
  21. package/lib/commonjs/components/FormField/FormField.js +3 -2
  22. package/lib/commonjs/components/ImageGallery/ImageGallery.js +132 -44
  23. package/lib/commonjs/components/Input/Input.js +144 -181
  24. package/lib/commonjs/components/ListItem/ListItem.js +90 -11
  25. package/lib/commonjs/components/Modal/Modal.js +55 -27
  26. package/lib/commonjs/components/NumberInput/NumberInput.js +60 -106
  27. package/lib/commonjs/components/OTPInput/OTPInput.js +65 -58
  28. package/lib/commonjs/components/PickerTrigger/PickerTrigger.js +185 -0
  29. package/lib/commonjs/components/{AppIcon → PickerTrigger}/index.js +4 -4
  30. package/lib/commonjs/components/ProgressBar/ProgressBar.js +19 -11
  31. package/lib/commonjs/components/Radio/Radio.js +11 -6
  32. package/lib/commonjs/components/Rating/Rating.js +85 -19
  33. package/lib/commonjs/components/SearchBar/SearchBar.js +84 -107
  34. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +22 -11
  35. package/lib/commonjs/components/Select/Select.js +62 -91
  36. package/lib/commonjs/components/Skeleton/Skeleton.js +131 -174
  37. package/lib/commonjs/components/Skeleton/SkeletonClock.js +117 -0
  38. package/lib/commonjs/components/Skeleton/SkeletonContent.js +164 -81
  39. package/lib/commonjs/components/Skeleton/SkeletonProvider.js +72 -10
  40. package/lib/commonjs/components/Skeleton/index.js +17 -16
  41. package/lib/commonjs/components/Slider/Slider.js +44 -25
  42. package/lib/commonjs/components/Stepper/Stepper.js +199 -29
  43. package/lib/commonjs/components/Swipeable/Swipeable.js +36 -19
  44. package/lib/commonjs/components/Switch/Switch.js +9 -2
  45. package/lib/commonjs/components/Tabs/Tabs.js +84 -21
  46. package/lib/commonjs/components/TimePicker/TimePicker.js +123 -45
  47. package/lib/commonjs/components/Toast/Toast.js +27 -16
  48. package/lib/commonjs/components/Tooltip/Tooltip.js +56 -32
  49. package/lib/commonjs/components/index.js +37 -37
  50. package/lib/commonjs/theme/tokens.js +55 -7
  51. package/lib/module/components/Accordion/Accordion.js +61 -20
  52. package/lib/module/components/AppBar/AppBar.js +29 -20
  53. package/lib/module/components/Avatar/Avatar.js +39 -9
  54. package/lib/module/components/Badge/Badge.js +67 -5
  55. package/lib/module/components/Banner/Banner.js +147 -67
  56. package/lib/module/components/BottomNavigation/BottomNavigation.js +37 -15
  57. package/lib/module/components/BottomSheet/BottomSheet.js +87 -52
  58. package/lib/module/components/Button/Button.js +12 -5
  59. package/lib/module/components/Card/Card.js +107 -17
  60. package/lib/module/components/Carousel/Carousel.js +67 -13
  61. package/lib/module/components/Checkbox/Checkbox.js +11 -7
  62. package/lib/module/components/Chip/Chip.js +45 -13
  63. package/lib/module/components/DatePicker/DatePicker.js +185 -76
  64. package/lib/module/components/DateRangePicker/DateRangePicker.js +134 -60
  65. package/lib/module/components/Dialog/Dialog.js +16 -10
  66. package/lib/module/components/Drawer/Drawer.js +13 -10
  67. package/lib/module/components/FieldBase/FieldBase.js +297 -0
  68. package/lib/module/components/FieldBase/index.js +4 -0
  69. package/lib/module/components/FloatingActionButton/FloatingActionButton.js +69 -44
  70. package/lib/module/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
  71. package/lib/module/components/FormField/FormField.js +3 -2
  72. package/lib/module/components/ImageGallery/ImageGallery.js +128 -40
  73. package/lib/module/components/Input/Input.js +144 -179
  74. package/lib/module/components/ListItem/ListItem.js +91 -12
  75. package/lib/module/components/Modal/Modal.js +55 -27
  76. package/lib/module/components/NumberInput/NumberInput.js +60 -106
  77. package/lib/module/components/OTPInput/OTPInput.js +65 -58
  78. package/lib/module/components/PickerTrigger/PickerTrigger.js +181 -0
  79. package/lib/module/components/PickerTrigger/index.js +4 -0
  80. package/lib/module/components/ProgressBar/ProgressBar.js +19 -11
  81. package/lib/module/components/Radio/Radio.js +11 -6
  82. package/lib/module/components/Rating/Rating.js +86 -20
  83. package/lib/module/components/SearchBar/SearchBar.js +84 -107
  84. package/lib/module/components/SegmentedControl/SegmentedControl.js +22 -11
  85. package/lib/module/components/Select/Select.js +62 -91
  86. package/lib/module/components/Skeleton/Skeleton.js +135 -175
  87. package/lib/module/components/Skeleton/SkeletonClock.js +110 -0
  88. package/lib/module/components/Skeleton/SkeletonContent.js +167 -84
  89. package/lib/module/components/Skeleton/SkeletonProvider.js +71 -10
  90. package/lib/module/components/Skeleton/index.js +3 -2
  91. package/lib/module/components/Slider/Slider.js +44 -25
  92. package/lib/module/components/Stepper/Stepper.js +201 -31
  93. package/lib/module/components/Swipeable/Swipeable.js +36 -19
  94. package/lib/module/components/Switch/Switch.js +9 -2
  95. package/lib/module/components/Tabs/Tabs.js +84 -21
  96. package/lib/module/components/TimePicker/TimePicker.js +123 -45
  97. package/lib/module/components/Toast/Toast.js +27 -16
  98. package/lib/module/components/Tooltip/Tooltip.js +56 -32
  99. package/lib/module/components/index.js +2 -2
  100. package/lib/module/theme/tokens.js +55 -7
  101. package/lib/typescript/commonjs/components/Accordion/Accordion.d.ts +10 -5
  102. package/lib/typescript/commonjs/components/AppBar/AppBar.d.ts +8 -0
  103. package/lib/typescript/commonjs/components/Avatar/Avatar.d.ts +12 -6
  104. package/lib/typescript/commonjs/components/Badge/Badge.d.ts +7 -6
  105. package/lib/typescript/commonjs/components/Banner/Banner.d.ts +17 -6
  106. package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +7 -0
  107. package/lib/typescript/commonjs/components/Card/Card.d.ts +17 -6
  108. package/lib/typescript/commonjs/components/Carousel/Carousel.d.ts +7 -6
  109. package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +9 -1
  110. package/lib/typescript/commonjs/components/Chip/Chip.d.ts +13 -6
  111. package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +38 -3
  112. package/lib/typescript/commonjs/components/DateRangePicker/DateRangePicker.d.ts +36 -3
  113. package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +13 -1
  114. package/lib/typescript/commonjs/components/FieldBase/FieldBase.d.ts +141 -0
  115. package/lib/typescript/commonjs/components/FieldBase/index.d.ts +3 -0
  116. package/lib/typescript/commonjs/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
  117. package/lib/typescript/commonjs/components/FloatingActionButton/index.d.ts +1 -1
  118. package/lib/typescript/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
  119. package/lib/typescript/commonjs/components/FormField/FormField.d.ts +7 -0
  120. package/lib/typescript/commonjs/components/ImageGallery/ImageGallery.d.ts +6 -4
  121. package/lib/typescript/commonjs/components/Input/Input.d.ts +6 -0
  122. package/lib/typescript/commonjs/components/ListItem/ListItem.d.ts +13 -6
  123. package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -0
  124. package/lib/typescript/commonjs/components/PickerTrigger/PickerTrigger.d.ts +57 -0
  125. package/lib/typescript/commonjs/components/PickerTrigger/index.d.ts +3 -0
  126. package/lib/typescript/commonjs/components/ProgressBar/ProgressBar.d.ts +2 -0
  127. package/lib/typescript/commonjs/components/Radio/Radio.d.ts +3 -0
  128. package/lib/typescript/commonjs/components/Rating/Rating.d.ts +9 -6
  129. package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  130. package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts +49 -20
  131. package/lib/typescript/commonjs/components/Skeleton/SkeletonClock.d.ts +60 -0
  132. package/lib/typescript/commonjs/components/Skeleton/SkeletonContent.d.ts +80 -19
  133. package/lib/typescript/commonjs/components/Skeleton/SkeletonProvider.d.ts +39 -5
  134. package/lib/typescript/commonjs/components/Skeleton/index.d.ts +6 -4
  135. package/lib/typescript/commonjs/components/Slider/Slider.d.ts +12 -1
  136. package/lib/typescript/commonjs/components/Stepper/Stepper.d.ts +18 -6
  137. package/lib/typescript/commonjs/components/Swipeable/Swipeable.d.ts +2 -0
  138. package/lib/typescript/commonjs/components/Switch/Switch.d.ts +1 -0
  139. package/lib/typescript/commonjs/components/Tabs/Tabs.d.ts +26 -2
  140. package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +36 -3
  141. package/lib/typescript/commonjs/components/Toast/Toast.d.ts +8 -0
  142. package/lib/typescript/commonjs/components/Tooltip/Tooltip.d.ts +7 -1
  143. package/lib/typescript/commonjs/components/index.d.ts +5 -5
  144. package/lib/typescript/commonjs/index.d.ts +1 -1
  145. package/lib/typescript/commonjs/theme/index.d.ts +1 -1
  146. package/lib/typescript/commonjs/theme/types.d.ts +553 -11
  147. package/lib/typescript/module/components/Accordion/Accordion.d.ts +10 -5
  148. package/lib/typescript/module/components/AppBar/AppBar.d.ts +8 -0
  149. package/lib/typescript/module/components/Avatar/Avatar.d.ts +12 -6
  150. package/lib/typescript/module/components/Badge/Badge.d.ts +7 -6
  151. package/lib/typescript/module/components/Banner/Banner.d.ts +17 -6
  152. package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +7 -0
  153. package/lib/typescript/module/components/Card/Card.d.ts +17 -6
  154. package/lib/typescript/module/components/Carousel/Carousel.d.ts +7 -6
  155. package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +9 -1
  156. package/lib/typescript/module/components/Chip/Chip.d.ts +13 -6
  157. package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +38 -3
  158. package/lib/typescript/module/components/DateRangePicker/DateRangePicker.d.ts +36 -3
  159. package/lib/typescript/module/components/Dialog/Dialog.d.ts +13 -1
  160. package/lib/typescript/module/components/FieldBase/FieldBase.d.ts +141 -0
  161. package/lib/typescript/module/components/FieldBase/index.d.ts +3 -0
  162. package/lib/typescript/module/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
  163. package/lib/typescript/module/components/FloatingActionButton/index.d.ts +1 -1
  164. package/lib/typescript/module/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
  165. package/lib/typescript/module/components/FormField/FormField.d.ts +7 -0
  166. package/lib/typescript/module/components/ImageGallery/ImageGallery.d.ts +6 -4
  167. package/lib/typescript/module/components/Input/Input.d.ts +6 -0
  168. package/lib/typescript/module/components/ListItem/ListItem.d.ts +13 -6
  169. package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -0
  170. package/lib/typescript/module/components/PickerTrigger/PickerTrigger.d.ts +57 -0
  171. package/lib/typescript/module/components/PickerTrigger/index.d.ts +3 -0
  172. package/lib/typescript/module/components/ProgressBar/ProgressBar.d.ts +2 -0
  173. package/lib/typescript/module/components/Radio/Radio.d.ts +3 -0
  174. package/lib/typescript/module/components/Rating/Rating.d.ts +9 -6
  175. package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  176. package/lib/typescript/module/components/Skeleton/Skeleton.d.ts +49 -20
  177. package/lib/typescript/module/components/Skeleton/SkeletonClock.d.ts +60 -0
  178. package/lib/typescript/module/components/Skeleton/SkeletonContent.d.ts +80 -19
  179. package/lib/typescript/module/components/Skeleton/SkeletonProvider.d.ts +39 -5
  180. package/lib/typescript/module/components/Skeleton/index.d.ts +6 -4
  181. package/lib/typescript/module/components/Slider/Slider.d.ts +12 -1
  182. package/lib/typescript/module/components/Stepper/Stepper.d.ts +18 -6
  183. package/lib/typescript/module/components/Swipeable/Swipeable.d.ts +2 -0
  184. package/lib/typescript/module/components/Switch/Switch.d.ts +1 -0
  185. package/lib/typescript/module/components/Tabs/Tabs.d.ts +26 -2
  186. package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +36 -3
  187. package/lib/typescript/module/components/Toast/Toast.d.ts +8 -0
  188. package/lib/typescript/module/components/Tooltip/Tooltip.d.ts +7 -1
  189. package/lib/typescript/module/components/index.d.ts +5 -5
  190. package/lib/typescript/module/index.d.ts +1 -1
  191. package/lib/typescript/module/theme/index.d.ts +1 -1
  192. package/lib/typescript/module/theme/types.d.ts +553 -11
  193. package/package.json +2 -6
  194. package/lib/commonjs/components/AppIcon/AppIcon.js +0 -120
  195. package/lib/commonjs/types/vector-icons.d.js +0 -2
  196. package/lib/module/components/AppIcon/AppIcon.js +0 -111
  197. package/lib/module/components/AppIcon/index.js +0 -4
  198. package/lib/module/types/vector-icons.d.js +0 -2
  199. package/lib/typescript/commonjs/components/AppIcon/AppIcon.d.ts +0 -20
  200. package/lib/typescript/commonjs/components/AppIcon/index.d.ts +0 -3
  201. package/lib/typescript/module/components/AppIcon/AppIcon.d.ts +0 -20
  202. package/lib/typescript/module/components/AppIcon/index.d.ts +0 -3
@@ -1,22 +1,57 @@
1
1
  "use strict";
2
2
 
3
- import React, { useEffect, useMemo, useRef, useState } from 'react';
4
- import { Animated, Easing, StyleSheet, View } from 'react-native';
5
- import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
3
+ /**
4
+ * Skeleton the leaf placeholder primitive.
5
+ *
6
+ * Every Skeleton on screen reads the shared shimmer/pulse clock from
7
+ * `SkeletonProvider` (see SkeletonClock.tsx). One native-driver loop per
8
+ * provider drives every instance, so 50 placeholders on a list don't spawn
9
+ * 50 timers and the shimmer bands never drift out of phase.
10
+ *
11
+ * Visual:
12
+ * - A View with the base color and `overflow: hidden` + radius gives the
13
+ * placeholder its shape.
14
+ * - For `animation: 'shimmer'`, an Animated.View carrying a 3-stop
15
+ * `LinearGradient` (transparent → highlight → transparent) translates
16
+ * across the box. The radius clips it to the right outline automatically.
17
+ * - For `animation: 'pulse'`, a full-fill Animated.View fades its opacity
18
+ * between 0 and 0.6. Cheap and useful for tiny shapes where a sweep
19
+ * would barely be visible.
20
+ * - For `animation: 'none'` (or when the OS Reduce Motion preference is
21
+ * on), just the base color renders.
22
+ *
23
+ * `variant` describes the SHAPE: rect (default), rounded (theme.radius.md),
24
+ * circle (50%), or text (small radius, slightly inset height). Set width /
25
+ * height directly for full control.
26
+ */
27
+
28
+ import React, { useMemo, useState } from 'react';
29
+ import { Animated, StyleSheet, View } from 'react-native';
30
+ import { useTheme } from "../../theme/index.js";
31
+
32
+ // `react-native-linear-gradient` is an OPTIONAL peer dep. When it's installed
33
+ // we sweep a real gradient band across the shimmer. When it isn't, we fall
34
+ // back to a solid-color band — still works, just less polished. This keeps
35
+ // the library deployable in apps that don't need gradients elsewhere.
36
+ let LinearGradientImpl = null;
37
+ try {
38
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
39
+ LinearGradientImpl = require('react-native-linear-gradient').default;
40
+ } catch {
41
+ // Optional peer; resolved lazily by consumers that need shimmer polish.
42
+ }
6
43
  import { Responsive } from "../../utils/index.js";
44
+ import { useSkeletonClock } from "./SkeletonClock.js";
7
45
  import { useSkeletonDefaults } from "./SkeletonProvider.js";
8
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
- const SPEED_DURATION = {
10
- slow: 1800,
11
- normal: 1200,
12
- fast: 800
13
- };
14
- const PULSE_DURATION = 1000;
15
- const AVATAR_SIZE = {
16
- sm: 32,
17
- md: 48,
18
- lg: 64
19
- };
46
+
47
+ /** Animation pattern. */
48
+
49
+ /** Sweep speed for the shimmer band. Ignored for pulse / none. */
50
+
51
+ /** Pre-defined shape archetype. Plays nicely with `width`/`height` overrides. */
52
+
53
+ /** `theme.radius` token name or a literal pixel value. */
54
+ import { jsx as _jsx } from "react/jsx-runtime";
20
55
  const resolveRadius = (theme, radius) => {
21
56
  if (typeof radius === 'number') return radius;
22
57
  return theme.radius[radius];
@@ -26,92 +61,128 @@ const resolveWidth = width => {
26
61
  if (typeof width === 'number') return width;
27
62
  return width;
28
63
  };
64
+ const radiusForShape = (theme, shape, width, height, explicit) => {
65
+ if (explicit !== undefined) return resolveRadius(theme, explicit);
66
+ switch (shape) {
67
+ case 'circle':
68
+ // Half the smallest known dimension. If width is a percentage we can't
69
+ // resolve here — fall back to height/2 which is the typical caller
70
+ // intent (square avatars).
71
+ return Math.floor(typeof width === 'number' ? Math.min(width, height) / 2 : height / 2);
72
+ case 'rounded':
73
+ return theme.radius.md;
74
+ case 'text':
75
+ return theme.radius.sm;
76
+ case 'rect':
77
+ default:
78
+ return theme.radius.sm;
79
+ }
80
+ };
29
81
  const Skeleton = ({
82
+ shape = 'rect',
30
83
  width = '100%',
31
84
  height = 16,
32
85
  radius,
33
86
  variant,
34
- speed,
87
+ speed: _speedProp,
35
88
  colors,
36
89
  style,
37
90
  testID
38
91
  }) => {
39
92
  const theme = useTheme();
40
93
  const defaults = useSkeletonDefaults();
94
+ const clock = useSkeletonClock();
41
95
  const resolvedVariant = variant ?? defaults.variant ?? 'shimmer';
42
- const resolvedSpeed = speed ?? defaults.speed ?? 'normal';
43
- const resolvedRadiusToken = radius ?? defaults.radius ?? 'sm';
96
+ const effectiveVariant = clock.enabled ? resolvedVariant : 'none';
44
97
  const backgroundColor = colors?.background ?? defaults.colors?.background ?? theme.colors.skeleton.background;
45
98
  const highlightColor = colors?.highlight ?? defaults.colors?.highlight ?? theme.colors.skeleton.highlight;
46
- const styles = useMemo(() => buildStyles(theme), [theme]);
47
- const borderRadius = resolveRadius(theme, resolvedRadiusToken);
99
+ const styles = useMemo(() => buildStyles(), []);
48
100
  const resolvedWidth = resolveWidth(width);
49
101
  const resolvedHeight = Responsive.size(height);
50
- const progress = useRef(createAnimatedValue(0)).current;
102
+ const borderRadius = radiusForShape(theme, shape, resolvedWidth, resolvedHeight, radius);
51
103
  const [containerWidth, setContainerWidth] = useState(0);
52
- useEffect(() => {
53
- setNativeValue(progress, 0);
54
- const duration = resolvedVariant === 'pulse' ? PULSE_DURATION : SPEED_DURATION[resolvedSpeed];
55
- const animation = resolvedVariant === 'pulse' ? Animated.loop(Animated.sequence([Animated.timing(progress, {
56
- toValue: 1,
57
- duration: duration / 2,
58
- easing: Easing.inOut(Easing.ease),
59
- useNativeDriver: true
60
- }), Animated.timing(progress, {
61
- toValue: 0,
62
- duration: duration / 2,
63
- easing: Easing.inOut(Easing.ease),
64
- useNativeDriver: true
65
- })])) : Animated.loop(Animated.timing(progress, {
66
- toValue: 1,
67
- duration,
68
- easing: Easing.linear,
69
- useNativeDriver: true
70
- }));
71
- animation.start();
72
- return () => {
73
- animation.stop();
74
- };
75
- }, [progress, resolvedSpeed, resolvedVariant]);
76
104
  const handleLayout = event => {
77
105
  const next = event.nativeEvent.layout.width;
78
106
  if (next !== containerWidth) setContainerWidth(next);
79
107
  };
108
+
109
+ // The shimmer band is wider than the box so the gradient feathers off the
110
+ // edges instead of popping at them. Width = 70% of container, capped to a
111
+ // sensible minimum so tiny placeholders still get a visible sweep.
112
+ const bandWidth = useMemo(() => {
113
+ if (containerWidth <= 0) return 0;
114
+ return Math.max(48, containerWidth * 0.7);
115
+ }, [containerWidth]);
116
+
117
+ // Interpolate the shared 0→1 clock into translateX. The band starts fully
118
+ // off the left edge and ends fully off the right edge, so each loop sweeps
119
+ // the full width regardless of how wide the placeholder is.
120
+ const translateX = useMemo(() => {
121
+ if (containerWidth <= 0) return 0;
122
+ return clock.shimmer.interpolate({
123
+ inputRange: [0, 1],
124
+ outputRange: [-bandWidth, containerWidth]
125
+ });
126
+ }, [clock.shimmer, bandWidth, containerWidth]);
80
127
  const overlay = useMemo(() => {
81
- if (resolvedVariant === 'pulse') {
128
+ if (effectiveVariant === 'none') return null;
129
+ if (effectiveVariant === 'pulse') {
130
+ // Pulse fades a full-fill highlight overlay in and out. Cheaper than
131
+ // shimmer and visible at any size.
82
132
  return /*#__PURE__*/_jsx(Animated.View, {
83
133
  pointerEvents: "none",
84
134
  style: [StyleSheet.absoluteFillObject, {
85
135
  backgroundColor: highlightColor,
86
- opacity: progress.interpolate({
136
+ opacity: clock.pulse.interpolate({
87
137
  inputRange: [0, 1],
88
- outputRange: [0, 0.6]
138
+ outputRange: [0, 0.55]
89
139
  })
90
140
  }]
91
141
  });
92
142
  }
93
143
  if (containerWidth <= 0) return null;
94
- const highlightWidth = Math.max(48, containerWidth * 0.6);
95
- const translateX = progress.interpolate({
96
- inputRange: [0, 1],
97
- outputRange: [-highlightWidth, containerWidth]
98
- });
144
+
145
+ // 3-stop gradient: transparent → highlight → transparent. Feathered
146
+ // edges feel premium; a solid band looks like a bug. When the optional
147
+ // gradient package isn't installed we render the band as a solid
148
+ // highlight rectangle — visibly different but still recognizably a
149
+ // shimmer effect.
99
150
  return /*#__PURE__*/_jsx(Animated.View, {
100
151
  pointerEvents: "none",
101
- style: [styles.shimmer, {
102
- width: highlightWidth,
103
- backgroundColor: highlightColor,
152
+ style: [styles.shimmerBand, {
153
+ width: bandWidth,
104
154
  transform: [{
105
155
  translateX
106
156
  }]
107
- }]
157
+ }],
158
+ children: LinearGradientImpl ? /*#__PURE__*/_jsx(LinearGradientImpl, {
159
+ colors: ['transparent', highlightColor, 'transparent'],
160
+ locations: [0, 0.5, 1],
161
+ start: {
162
+ x: 0,
163
+ y: 0.5
164
+ },
165
+ end: {
166
+ x: 1,
167
+ y: 0.5
168
+ },
169
+ style: StyleSheet.absoluteFillObject
170
+ }) : /*#__PURE__*/_jsx(View, {
171
+ style: [StyleSheet.absoluteFillObject, {
172
+ backgroundColor: highlightColor,
173
+ opacity: 0.55
174
+ }]
175
+ })
108
176
  });
109
- }, [containerWidth, progress, styles.shimmer, highlightColor, resolvedVariant]);
177
+ }, [effectiveVariant, highlightColor, clock.pulse, containerWidth, styles.shimmerBand, bandWidth, translateX]);
110
178
  return /*#__PURE__*/_jsx(View, {
111
179
  onLayout: handleLayout,
112
180
  accessible: true,
113
181
  accessibilityLabel: "Loading",
114
182
  accessibilityRole: "progressbar",
183
+ accessibilityState: {
184
+ busy: true
185
+ },
115
186
  accessibilityLiveRegion: "polite",
116
187
  testID: testID,
117
188
  style: [styles.base, {
@@ -132,9 +203,9 @@ const SkeletonCircle = ({
132
203
  const diameter = Responsive.size(size);
133
204
  return /*#__PURE__*/_jsx(Skeleton, {
134
205
  ...rest,
206
+ shape: "circle",
135
207
  width: diameter,
136
208
  height: size,
137
- radius: "full",
138
209
  style: [{
139
210
  width: diameter,
140
211
  height: diameter,
@@ -168,6 +239,7 @@ const SkeletonText = ({
168
239
  const isLast = index === safeLines - 1;
169
240
  const lineWidth = isLast && safeLines > 1 ? lastLineWidth : width;
170
241
  return /*#__PURE__*/_jsx(Skeleton, {
242
+ shape: "text",
171
243
  width: lineWidth,
172
244
  height: lineHeight,
173
245
  radius: radius,
@@ -181,129 +253,17 @@ const SkeletonText = ({
181
253
  });
182
254
  };
183
255
  SkeletonText.displayName = 'SkeletonText';
184
- const SkeletonAvatar = ({
185
- size = 'md',
186
- ...rest
187
- }) => {
188
- return /*#__PURE__*/_jsx(SkeletonCircle, {
189
- ...rest,
190
- size: AVATAR_SIZE[size]
191
- });
192
- };
193
- SkeletonAvatar.displayName = 'SkeletonAvatar';
194
- const SkeletonCard = ({
195
- variant,
196
- speed,
197
- radius = 'md',
198
- style,
199
- testID
200
- }) => {
201
- const theme = useTheme();
202
- return /*#__PURE__*/_jsxs(View, {
203
- style: [{
204
- padding: theme.spacing.md
205
- }, style],
206
- testID: testID,
207
- children: [/*#__PURE__*/_jsxs(View, {
208
- style: {
209
- flexDirection: 'row',
210
- alignItems: 'center',
211
- marginBottom: theme.spacing.md
212
- },
213
- children: [/*#__PURE__*/_jsx(SkeletonAvatar, {
214
- size: "md",
215
- variant: variant,
216
- speed: speed
217
- }), /*#__PURE__*/_jsxs(View, {
218
- style: {
219
- flex: 1,
220
- marginLeft: theme.spacing.sm
221
- },
222
- children: [/*#__PURE__*/_jsx(Skeleton, {
223
- width: "60%",
224
- height: 14,
225
- radius: radius,
226
- variant: variant,
227
- speed: speed,
228
- style: {
229
- marginBottom: theme.spacing.xs
230
- }
231
- }), /*#__PURE__*/_jsx(Skeleton, {
232
- width: "40%",
233
- height: 12,
234
- radius: radius,
235
- variant: variant,
236
- speed: speed
237
- })]
238
- })]
239
- }), /*#__PURE__*/_jsx(SkeletonText, {
240
- lines: 2,
241
- fontSize: 14,
242
- variant: variant,
243
- speed: speed,
244
- radius: radius
245
- })]
246
- });
247
- };
248
- SkeletonCard.displayName = 'SkeletonCard';
249
- const SkeletonListItem = ({
250
- avatarSize = 'md',
251
- variant,
252
- speed,
253
- radius = 'sm',
254
- style,
255
- testID
256
- }) => {
257
- const theme = useTheme();
258
- return /*#__PURE__*/_jsxs(View, {
259
- style: [{
260
- flexDirection: 'row',
261
- alignItems: 'center',
262
- paddingHorizontal: theme.spacing.md,
263
- paddingVertical: theme.spacing.sm
264
- }, style],
265
- testID: testID,
266
- children: [/*#__PURE__*/_jsx(SkeletonAvatar, {
267
- size: avatarSize,
268
- variant: variant,
269
- speed: speed
270
- }), /*#__PURE__*/_jsxs(View, {
271
- style: {
272
- flex: 1,
273
- marginLeft: theme.spacing.sm
274
- },
275
- children: [/*#__PURE__*/_jsx(Skeleton, {
276
- width: "70%",
277
- height: 14,
278
- radius: radius,
279
- variant: variant,
280
- speed: speed,
281
- style: {
282
- marginBottom: theme.spacing.xs
283
- }
284
- }), /*#__PURE__*/_jsx(Skeleton, {
285
- width: "45%",
286
- height: 12,
287
- radius: radius,
288
- variant: variant,
289
- speed: speed
290
- })]
291
- })]
292
- });
293
- };
294
- SkeletonListItem.displayName = 'SkeletonListItem';
295
- const buildStyles = _theme => StyleSheet.create({
256
+ const buildStyles = () => StyleSheet.create({
296
257
  base: {
297
258
  overflow: 'hidden'
298
259
  },
299
- shimmer: {
260
+ shimmerBand: {
300
261
  position: 'absolute',
301
262
  top: 0,
302
263
  bottom: 0,
303
- left: 0,
304
- opacity: 0.55
264
+ left: 0
305
265
  }
306
266
  });
307
- export { Skeleton, SkeletonCircle, SkeletonText, SkeletonAvatar, SkeletonCard, SkeletonListItem };
267
+ export { Skeleton, SkeletonCircle, SkeletonText };
308
268
  export default Skeleton;
309
269
  //# sourceMappingURL=Skeleton.js.map
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * SkeletonClock — single shared animation tick for every <Skeleton> on screen.
5
+ *
6
+ * Why this exists: previously every Skeleton primitive ran its own
7
+ * `Animated.loop` on its own `Animated.Value`. A list of 20 placeholders =
8
+ * 20 independent native-driver timers, each starting at a slightly different
9
+ * mount frame, so their shimmer bands drift out of phase within ~1s and the
10
+ * surface feels noisy. CSS-driven web skeleton libs (react-loading-skeleton,
11
+ * MUI) avoid this because the browser owns a single timeline. We emulate
12
+ * that on RN by hoisting the loop into context.
13
+ *
14
+ * The clock produces a value in `[0, 1)` that wraps every `duration` ms. Each
15
+ * Skeleton interpolates that value into its own translateX / opacity output.
16
+ * One native-driver loop, no drift, ~zero JS cost.
17
+ */
18
+
19
+ import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
20
+ import { Animated, Easing } from 'react-native';
21
+ import { createAnimatedValue } from "../../theme/index.js";
22
+ import { jsx as _jsx } from "react/jsx-runtime";
23
+ const SHIMMER_DURATION = {
24
+ slow: 1800,
25
+ normal: 1200,
26
+ fast: 800
27
+ };
28
+ const PULSE_DURATION = 1000;
29
+ const SkeletonClockContext = /*#__PURE__*/createContext(null);
30
+ /**
31
+ * Owns the loops. Mount one of these inside `SkeletonProvider`; every
32
+ * `<Skeleton>` below it shares the same animated values.
33
+ */
34
+ export const SkeletonClockProvider = ({
35
+ speed,
36
+ enabled,
37
+ variant: _variant,
38
+ children
39
+ }) => {
40
+ const shimmer = useRef(createAnimatedValue(0)).current;
41
+ const pulse = useRef(createAnimatedValue(0)).current;
42
+ useEffect(() => {
43
+ if (!enabled) {
44
+ // Park the values at a deterministic "off" state so any consumer that
45
+ // happens to be reading them still gets a visible (static) skeleton.
46
+ shimmer.setValue(0);
47
+ pulse.setValue(0.5);
48
+ return;
49
+ }
50
+
51
+ // Both loops use the native driver — the JS thread doesn't tick for
52
+ // either. Both run continuously; consumers read whichever they need.
53
+ // The negligible cost of running the *other* loop is worth keeping
54
+ // variant switching instant (no remount, no loop teardown).
55
+ const shimmerLoop = Animated.loop(Animated.timing(shimmer, {
56
+ toValue: 1,
57
+ duration: SHIMMER_DURATION[speed],
58
+ easing: Easing.linear,
59
+ useNativeDriver: true
60
+ }));
61
+ const pulseLoop = Animated.loop(Animated.sequence([Animated.timing(pulse, {
62
+ toValue: 1,
63
+ duration: PULSE_DURATION / 2,
64
+ easing: Easing.inOut(Easing.ease),
65
+ useNativeDriver: true
66
+ }), Animated.timing(pulse, {
67
+ toValue: 0,
68
+ duration: PULSE_DURATION / 2,
69
+ easing: Easing.inOut(Easing.ease),
70
+ useNativeDriver: true
71
+ })]));
72
+ shimmerLoop.start();
73
+ pulseLoop.start();
74
+ return () => {
75
+ shimmerLoop.stop();
76
+ pulseLoop.stop();
77
+ };
78
+ // `variant` is intentionally NOT a dependency — both loops always run
79
+ // so switching variants is a single render with no loop teardown.
80
+ // eslint-disable-next-line react-hooks/exhaustive-deps
81
+ }, [speed, enabled]);
82
+ const value = useMemo(() => ({
83
+ shimmer,
84
+ pulse,
85
+ enabled
86
+ }), [shimmer, pulse, enabled]);
87
+ return /*#__PURE__*/_jsx(SkeletonClockContext.Provider, {
88
+ value: value,
89
+ children: children
90
+ });
91
+ };
92
+ SkeletonClockProvider.displayName = 'SkeletonClockProvider';
93
+
94
+ /**
95
+ * Read the active clock. Returns a fallback "always-still" clock when no
96
+ * provider is mounted, so the primitives still render (statically) outside
97
+ * one — keeps demo/storybook usage friction-free.
98
+ */
99
+ export const useSkeletonClock = () => {
100
+ const ctx = useContext(SkeletonClockContext);
101
+ if (ctx) return ctx;
102
+ // Fallback: a permanently-stopped clock. Created once at module scope.
103
+ return fallbackClock;
104
+ };
105
+ const fallbackClock = {
106
+ shimmer: createAnimatedValue(0),
107
+ pulse: createAnimatedValue(0.5),
108
+ enabled: false
109
+ };
110
+ //# sourceMappingURL=SkeletonClock.js.map