@retray-dev/ui-kit 7.0.1 → 9.0.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.
- package/COMPONENTS.md +554 -11
- package/EXAMPLES.md +2 -2
- package/README.md +14 -8
- package/dist/Accordion.js +57 -5
- package/dist/Accordion.mjs +4 -3
- package/dist/AlertBanner.js +4 -1
- package/dist/AlertBanner.mjs +3 -2
- package/dist/AppHeader.d.mts +40 -0
- package/dist/AppHeader.d.ts +40 -0
- package/dist/AppHeader.js +515 -0
- package/dist/AppHeader.mjs +10 -0
- package/dist/Avatar.js +39 -29
- package/dist/Avatar.mjs +2 -1
- package/dist/Badge.js +11 -1
- package/dist/Badge.mjs +2 -1
- package/dist/Button.d.mts +8 -3
- package/dist/Button.d.ts +8 -3
- package/dist/Button.js +126 -108
- package/dist/Button.mjs +6 -5
- package/dist/ButtonGroup.mjs +1 -0
- package/dist/Card.js +90 -70
- package/dist/Card.mjs +5 -4
- package/dist/CategoryStrip.js +79 -22
- package/dist/CategoryStrip.mjs +6 -6
- package/dist/Checkbox.js +118 -86
- package/dist/Checkbox.mjs +5 -5
- package/dist/Chip.js +113 -80
- package/dist/Chip.mjs +5 -5
- package/dist/ConfirmDialog.js +140 -110
- package/dist/ConfirmDialog.mjs +7 -6
- package/dist/CurrencyDisplay.mjs +1 -0
- package/dist/CurrencyInput.d.mts +1 -1
- package/dist/CurrencyInput.d.ts +1 -1
- package/dist/CurrencyInput.js +9 -5
- package/dist/CurrencyInput.mjs +5 -4
- package/dist/DetailRow.mjs +1 -0
- package/dist/EmptyState.js +131 -111
- package/dist/EmptyState.mjs +7 -6
- package/dist/ErrorBoundary.d.mts +42 -0
- package/dist/ErrorBoundary.d.ts +42 -0
- package/dist/ErrorBoundary.js +351 -0
- package/dist/ErrorBoundary.mjs +7 -0
- package/dist/Form.mjs +1 -0
- package/dist/HolographicCard.d.mts +55 -0
- package/dist/HolographicCard.d.ts +55 -0
- package/dist/HolographicCard.js +316 -0
- package/dist/HolographicCard.mjs +191 -0
- package/dist/IconButton.d.mts +8 -3
- package/dist/IconButton.d.ts +8 -3
- package/dist/IconButton.js +115 -98
- package/dist/IconButton.mjs +5 -4
- package/dist/ImageViewer.d.mts +23 -0
- package/dist/ImageViewer.d.ts +23 -0
- package/dist/ImageViewer.js +582 -0
- package/dist/ImageViewer.mjs +8 -0
- package/dist/Input.mjs +4 -3
- package/dist/LabelValue.mjs +1 -0
- package/dist/ListGroup.mjs +1 -0
- package/dist/ListItem.js +131 -117
- package/dist/ListItem.mjs +6 -5
- package/dist/MediaCard.js +54 -6
- package/dist/MediaCard.mjs +6 -5
- package/dist/MenuGroup.mjs +1 -0
- package/dist/MenuItem.js +91 -79
- package/dist/MenuItem.mjs +6 -5
- package/dist/MonthPicker.d.mts +10 -2
- package/dist/MonthPicker.d.ts +10 -2
- package/dist/MonthPicker.js +80 -17
- package/dist/MonthPicker.mjs +3 -2
- package/dist/PagerDots.d.mts +35 -0
- package/dist/PagerDots.d.ts +35 -0
- package/dist/PagerDots.js +392 -0
- package/dist/PagerDots.mjs +7 -0
- package/dist/Pressable.d.mts +5 -5
- package/dist/Pressable.d.ts +5 -5
- package/dist/Pressable.js +97 -86
- package/dist/Pressable.mjs +5 -4
- package/dist/PricingCard.d.mts +50 -0
- package/dist/PricingCard.d.ts +50 -0
- package/dist/PricingCard.js +636 -0
- package/dist/PricingCard.mjs +11 -0
- package/dist/Progress.mjs +3 -2
- package/dist/RadioGroup.js +81 -30
- package/dist/RadioGroup.mjs +5 -5
- package/dist/RetrayProvider.d.mts +2 -0
- package/dist/RetrayProvider.d.ts +2 -0
- package/dist/RetrayProvider.js +214 -0
- package/dist/RetrayProvider.mjs +5 -0
- package/dist/Select.js +51 -4
- package/dist/Select.mjs +5 -4
- package/dist/SelectableGrid.d.mts +44 -0
- package/dist/SelectableGrid.d.ts +44 -0
- package/dist/SelectableGrid.js +448 -0
- package/dist/SelectableGrid.mjs +9 -0
- package/dist/Separator.mjs +1 -0
- package/dist/Sheet.d.mts +13 -1
- package/dist/Sheet.d.ts +13 -1
- package/dist/Sheet.js +115 -5
- package/dist/Sheet.mjs +4 -2
- package/dist/Skeleton.d.mts +50 -0
- package/dist/Skeleton.d.ts +50 -0
- package/dist/Skeleton.js +61 -0
- package/dist/Skeleton.mjs +4 -2
- package/dist/Slider.js +51 -4
- package/dist/Slider.mjs +3 -2
- package/dist/Spinner.js +28 -7
- package/dist/Spinner.mjs +2 -1
- package/dist/Switch.js +98 -48
- package/dist/Switch.mjs +4 -3
- package/dist/TabBar.d.mts +42 -0
- package/dist/TabBar.d.ts +42 -0
- package/dist/TabBar.js +361 -0
- package/dist/TabBar.mjs +6 -0
- package/dist/Tabs.js +92 -62
- package/dist/Tabs.mjs +5 -4
- package/dist/Text.js +16 -0
- package/dist/Text.mjs +2 -1
- package/dist/Textarea.mjs +4 -3
- package/dist/Toast.d.mts +7 -7
- package/dist/Toast.d.ts +7 -7
- package/dist/Toast.mjs +1 -0
- package/dist/Toggle.d.mts +6 -3
- package/dist/Toggle.d.ts +6 -3
- package/dist/Toggle.js +135 -120
- package/dist/Toggle.mjs +5 -5
- package/dist/VirtualList.mjs +1 -0
- package/dist/{chunk-7H2OR44A.mjs → chunk-26BCI223.mjs} +1 -1
- package/dist/{chunk-CRYBX2CM.mjs → chunk-2TFTAWVJ.mjs} +44 -59
- package/dist/chunk-3DKJ2GIC.mjs +30 -0
- package/dist/{chunk-KWCPOM6W.mjs → chunk-3U4SSNWP.mjs} +32 -48
- package/dist/chunk-4I7D47FH.mjs +139 -0
- package/dist/chunk-4K625MVM.mjs +142 -0
- package/dist/{chunk-MN7OG7IY.mjs → chunk-6OAZJ577.mjs} +6 -4
- package/dist/{chunk-L7E7TVEZ.mjs → chunk-756RAKE4.mjs} +2 -2
- package/dist/{chunk-HSPSMN6U.mjs → chunk-7QHVVCB3.mjs} +2 -2
- package/dist/{chunk-URLL5JBR.mjs → chunk-A3A6KNQN.mjs} +3 -3
- package/dist/chunk-AJ7ZDNBT.mjs +120 -0
- package/dist/{chunk-FTLJOUOQ.mjs → chunk-AV4EMIRH.mjs} +25 -28
- package/dist/chunk-AZJF2BLK.mjs +115 -0
- package/dist/chunk-BNP626TY.mjs +159 -0
- package/dist/{chunk-5IKW3VNC.mjs → chunk-DVK4G2GT.mjs} +17 -1
- package/dist/{chunk-6LQYY7HC.mjs → chunk-EH745HE5.mjs} +2 -2
- package/dist/chunk-EJ7ZPXOH.mjs +163 -0
- package/dist/{chunk-RKLHUDZS.mjs → chunk-GD6KXMG5.mjs} +29 -15
- package/dist/{chunk-RR2VQLKE.mjs → chunk-GQYFLP3D.mjs} +14 -17
- package/dist/{chunk-Y6MXOREN.mjs → chunk-ID72TK46.mjs} +8 -17
- package/dist/{chunk-NQGVLMWG.mjs → chunk-JMOZEC77.mjs} +1 -1
- package/dist/{chunk-GCWOGZYL.mjs → chunk-JT7HKXRB.mjs} +39 -29
- package/dist/{chunk-LWG526VX.mjs → chunk-KIHCWCWL.mjs} +47 -62
- package/dist/chunk-LXJIIOYQ.mjs +104 -0
- package/dist/{chunk-SBZYEV4S.mjs → chunk-M6ZXVBTK.mjs} +5 -2
- package/dist/{chunk-XDMN67KV.mjs → chunk-MAC465BB.mjs} +10 -8
- package/dist/chunk-MBMXYJJV.mjs +36 -0
- package/dist/chunk-MLF3EZFW.mjs +119 -0
- package/dist/chunk-NA7PARID.mjs +147 -0
- package/dist/{chunk-QXGYKWI7.mjs → chunk-O3HA6TYM.mjs} +9 -4
- package/dist/{chunk-63357L2X.mjs → chunk-OB4JUQ3O.mjs} +1 -1
- package/dist/{chunk-AU2VDY4P.mjs → chunk-PFZTM6D5.mjs} +52 -4
- package/dist/chunk-QKH5ZOD5.mjs +97 -0
- package/dist/{chunk-KZJRQOIU.mjs → chunk-TERDKCLE.mjs} +11 -1
- package/dist/{chunk-U4N7WF4Z.mjs → chunk-UREA2GYY.mjs} +28 -23
- package/dist/{chunk-TAJ2PQ2O.mjs → chunk-VGTDN7SW.mjs} +7 -6
- package/dist/{chunk-URDE3EUU.mjs → chunk-VQ57HWPL.mjs} +27 -15
- package/dist/chunk-WBOOUHSS.mjs +62 -0
- package/dist/{chunk-GNGLDL6Z.mjs → chunk-WJLKJMKR.mjs} +18 -0
- package/dist/{chunk-YZJAFS4P.mjs → chunk-X4G6APW6.mjs} +22 -19
- package/dist/chunk-Y6FXYEAI.mjs +8 -0
- package/dist/chunk-YFZ3ELX5.mjs +16 -0
- package/dist/{chunk-QCNARS3X.mjs → chunk-YNROWHQJ.mjs} +1 -1
- package/dist/chunk-Z4BVUWW6.mjs +196 -0
- package/dist/{chunk-GPOUINK5.mjs → chunk-ZJKGQMYH.mjs} +10 -27
- package/dist/index-wt-orHUi.d.mts +85 -0
- package/dist/index-wt-orHUi.d.ts +85 -0
- package/dist/index.d.mts +59 -51
- package/dist/index.d.ts +59 -51
- package/dist/index.js +1940 -744
- package/dist/index.mjs +49 -39
- package/package.json +35 -5
- package/src/components/Accordion/Accordion.tsx +12 -1
- package/src/components/AlertBanner/AlertBanner.tsx +5 -0
- package/src/components/AppHeader/AppHeader.tsx +172 -0
- package/src/components/AppHeader/index.ts +1 -0
- package/src/components/Avatar/Avatar.tsx +10 -2
- package/src/components/Badge/Badge.tsx +8 -1
- package/src/components/Button/Button.tsx +20 -27
- package/src/components/Card/Card.tsx +12 -23
- package/src/components/CategoryStrip/CategoryStrip.tsx +17 -21
- package/src/components/Checkbox/Checkbox.tsx +26 -40
- package/src/components/Chip/Chip.tsx +24 -33
- package/src/components/CurrencyInput/CurrencyInput.tsx +10 -8
- package/src/components/EmptyState/EmptyState.tsx +2 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +153 -0
- package/src/components/ErrorBoundary/index.ts +1 -0
- package/src/components/HolographicCard/HolographicCard.tsx +315 -0
- package/src/components/HolographicCard/index.ts +1 -0
- package/src/components/IconButton/IconButton.tsx +19 -27
- package/src/components/ImageViewer/ImageViewer.tsx +290 -0
- package/src/components/ImageViewer/index.ts +1 -0
- package/src/components/ListItem/ListItem.tsx +70 -67
- package/src/components/MediaCard/MediaCard.tsx +8 -2
- package/src/components/MenuItem/MenuItem.tsx +10 -25
- package/src/components/MonthPicker/MonthPicker.tsx +39 -13
- package/src/components/MonthPicker/index.ts +1 -1
- package/src/components/PagerDots/PagerDots.tsx +200 -0
- package/src/components/PagerDots/index.ts +1 -0
- package/src/components/Pressable/Pressable.tsx +19 -35
- package/src/components/PricingCard/PricingCard.tsx +220 -0
- package/src/components/PricingCard/index.ts +1 -0
- package/src/components/RadioGroup/RadioGroup.tsx +14 -27
- package/src/components/RetrayProvider/RetrayProvider.tsx +59 -0
- package/src/components/RetrayProvider/index.ts +1 -0
- package/src/components/SelectableGrid/SelectableGrid.tsx +205 -0
- package/src/components/SelectableGrid/index.ts +1 -0
- package/src/components/Sheet/Sheet.tsx +65 -1
- package/src/components/Skeleton/Skeleton.tsx +142 -1
- package/src/components/Spinner/Spinner.tsx +17 -2
- package/src/components/Switch/Switch.tsx +30 -58
- package/src/components/TabBar/TabBar.tsx +169 -0
- package/src/components/TabBar/index.ts +1 -0
- package/src/components/Tabs/Tabs.tsx +23 -26
- package/src/components/Text/Text.tsx +2 -0
- package/src/components/Toggle/Toggle.tsx +35 -51
- package/src/fonts.ts +4 -1
- package/src/index.ts +23 -2
- package/src/utils/animations.ts +29 -1
- package/src/utils/fontGuard.ts +34 -0
- package/src/utils/haptics.ts +211 -9
- package/src/utils/pressable.ts +66 -0
- package/dist/chunk-76PFOSM2.mjs +0 -41
- package/dist/chunk-DITNP6PL.mjs +0 -106
- package/dist/chunk-JBLL7U3U.mjs +0 -64
- package/dist/chunk-LG4DO3DK.mjs +0 -174
- package/dist/chunk-RMMK64W5.mjs +0 -54
- package/dist/chunk-RTC3CFXF.mjs +0 -29
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React25 = require('react');
|
|
4
4
|
var reactNative = require('react-native');
|
|
5
|
-
var Animated9 = require('react-native-reanimated');
|
|
6
5
|
var reactNativeSizeMatters = require('react-native-size-matters');
|
|
7
6
|
var AntDesign = require('@expo/vector-icons/AntDesign');
|
|
8
7
|
var Entypo = require('@expo/vector-icons/Entypo');
|
|
@@ -10,27 +9,37 @@ var Feather = require('@expo/vector-icons/Feather');
|
|
|
10
9
|
var FontAwesome5 = require('@expo/vector-icons/FontAwesome5');
|
|
11
10
|
var MaterialIcons = require('@expo/vector-icons/MaterialIcons');
|
|
12
11
|
var Ionicons = require('@expo/vector-icons/Ionicons');
|
|
12
|
+
var pressto = require('pressto');
|
|
13
|
+
var Animated13 = require('react-native-reanimated');
|
|
14
|
+
var expoFont = require('expo-font');
|
|
13
15
|
var vectorIcons = require('@expo/vector-icons');
|
|
14
16
|
var expoLinearGradient = require('expo-linear-gradient');
|
|
17
|
+
var reactNativeEase = require('react-native-ease');
|
|
15
18
|
var RNSlider = require('@react-native-community/slider');
|
|
16
19
|
var bottomSheet = require('@gorhom/bottom-sheet');
|
|
17
20
|
var reactNativeSafeAreaContext = require('react-native-safe-area-context');
|
|
18
21
|
var picker = require('@react-native-picker/picker');
|
|
19
22
|
var sonnerNative = require('sonner-native');
|
|
23
|
+
var reactNativeGestureHandler = require('react-native-gesture-handler');
|
|
20
24
|
|
|
21
25
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
26
|
|
|
23
|
-
var
|
|
24
|
-
var Animated9__default = /*#__PURE__*/_interopDefault(Animated9);
|
|
27
|
+
var React25__default = /*#__PURE__*/_interopDefault(React25);
|
|
25
28
|
var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
|
|
26
29
|
var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
|
|
27
30
|
var Feather__default = /*#__PURE__*/_interopDefault(Feather);
|
|
28
31
|
var FontAwesome5__default = /*#__PURE__*/_interopDefault(FontAwesome5);
|
|
29
32
|
var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
|
|
30
33
|
var Ionicons__default = /*#__PURE__*/_interopDefault(Ionicons);
|
|
34
|
+
var Animated13__default = /*#__PURE__*/_interopDefault(Animated13);
|
|
31
35
|
var RNSlider__default = /*#__PURE__*/_interopDefault(RNSlider);
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
38
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
39
|
+
}) : x)(function(x) {
|
|
40
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
41
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
42
|
+
});
|
|
34
43
|
|
|
35
44
|
// src/theme/colorUtils.ts
|
|
36
45
|
function hexToRgb(hex) {
|
|
@@ -158,52 +167,186 @@ function deriveColors(t, scheme) {
|
|
|
158
167
|
}
|
|
159
168
|
|
|
160
169
|
// src/theme/ThemeProvider.tsx
|
|
161
|
-
var ThemeContext =
|
|
170
|
+
var ThemeContext = React25.createContext({
|
|
162
171
|
colors: deriveColors(defaultLight, "light"),
|
|
163
172
|
colorScheme: "light"
|
|
164
173
|
});
|
|
165
174
|
function ThemeProvider({ children, theme, colorScheme = "system" }) {
|
|
166
175
|
const systemScheme = reactNative.useColorScheme() ?? "light";
|
|
167
176
|
const resolvedScheme = colorScheme === "system" ? systemScheme : colorScheme;
|
|
168
|
-
const colors =
|
|
177
|
+
const colors = React25.useMemo(() => {
|
|
169
178
|
const base = resolvedScheme === "dark" ? defaultDark : defaultLight;
|
|
170
179
|
const override = resolvedScheme === "dark" ? theme?.dark : theme?.light;
|
|
171
180
|
const merged = override ? { ...base, ...override } : base;
|
|
172
181
|
return deriveColors(merged, resolvedScheme);
|
|
173
182
|
}, [resolvedScheme, theme]);
|
|
174
|
-
return /* @__PURE__ */
|
|
183
|
+
return /* @__PURE__ */ React25__default.default.createElement(ThemeContext.Provider, { value: { colors, colorScheme: resolvedScheme } }, children);
|
|
175
184
|
}
|
|
176
185
|
function useTheme() {
|
|
177
|
-
const context =
|
|
186
|
+
const context = React25.useContext(ThemeContext);
|
|
178
187
|
if (!context) {
|
|
179
188
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
180
189
|
}
|
|
181
190
|
return context;
|
|
182
191
|
}
|
|
183
192
|
var _haptics = null;
|
|
193
|
+
var _hapticsLoaded = false;
|
|
184
194
|
async function getHaptics() {
|
|
185
195
|
if (reactNative.Platform.OS === "web") return null;
|
|
186
|
-
if (!
|
|
187
|
-
|
|
196
|
+
if (!_hapticsLoaded) {
|
|
197
|
+
_hapticsLoaded = true;
|
|
198
|
+
try {
|
|
199
|
+
_haptics = await import('expo-haptics');
|
|
200
|
+
} catch {
|
|
201
|
+
_haptics = null;
|
|
202
|
+
}
|
|
188
203
|
}
|
|
189
204
|
return _haptics;
|
|
190
205
|
}
|
|
206
|
+
var _pulsar = null;
|
|
207
|
+
var _pulsarChecked = false;
|
|
208
|
+
var _pulsarAvailable = false;
|
|
209
|
+
function isPulsarNativeRegistered() {
|
|
210
|
+
try {
|
|
211
|
+
const g = globalThis;
|
|
212
|
+
if (typeof g.__turboModuleProxy === "function") {
|
|
213
|
+
return g.__turboModuleProxy("RNPulsar") != null;
|
|
214
|
+
}
|
|
215
|
+
return reactNative.NativeModules?.RNPulsar != null;
|
|
216
|
+
} catch {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function getPulsar() {
|
|
221
|
+
if (reactNative.Platform.OS === "web") return null;
|
|
222
|
+
if (!_pulsarChecked) {
|
|
223
|
+
_pulsarChecked = true;
|
|
224
|
+
try {
|
|
225
|
+
if (isPulsarNativeRegistered()) {
|
|
226
|
+
_pulsar = __require("react-native-pulsar");
|
|
227
|
+
_pulsarAvailable = true;
|
|
228
|
+
}
|
|
229
|
+
} catch {
|
|
230
|
+
_pulsar = null;
|
|
231
|
+
_pulsarAvailable = false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return _pulsarAvailable ? _pulsar : null;
|
|
235
|
+
}
|
|
191
236
|
function selectionAsync() {
|
|
192
237
|
if (reactNative.Platform.OS === "web") return;
|
|
193
|
-
getHaptics().then((h) =>
|
|
238
|
+
getHaptics().then((h) => {
|
|
239
|
+
if (h) {
|
|
240
|
+
h.selectionAsync();
|
|
241
|
+
} else {
|
|
242
|
+
getPulsar()?.Presets.System.selection();
|
|
243
|
+
}
|
|
244
|
+
});
|
|
194
245
|
}
|
|
195
246
|
function impactLight() {
|
|
196
247
|
if (reactNative.Platform.OS === "web") return;
|
|
197
|
-
getHaptics().then((h) =>
|
|
248
|
+
getHaptics().then((h) => {
|
|
249
|
+
if (h) {
|
|
250
|
+
h.impactAsync(h.ImpactFeedbackStyle.Light);
|
|
251
|
+
} else {
|
|
252
|
+
getPulsar()?.Presets.System.impactLight();
|
|
253
|
+
}
|
|
254
|
+
});
|
|
198
255
|
}
|
|
199
256
|
function impactMedium() {
|
|
200
257
|
if (reactNative.Platform.OS === "web") return;
|
|
201
|
-
getHaptics().then((h) =>
|
|
258
|
+
getHaptics().then((h) => {
|
|
259
|
+
if (h) {
|
|
260
|
+
h.impactAsync(h.ImpactFeedbackStyle.Medium);
|
|
261
|
+
} else {
|
|
262
|
+
getPulsar()?.Presets.System.impactMedium();
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function impactHeavy() {
|
|
267
|
+
if (reactNative.Platform.OS === "web") return;
|
|
268
|
+
getHaptics().then((h) => {
|
|
269
|
+
if (h) {
|
|
270
|
+
h.impactAsync(h.ImpactFeedbackStyle.Heavy);
|
|
271
|
+
} else {
|
|
272
|
+
getPulsar()?.Presets.System.impactHeavy();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
202
275
|
}
|
|
203
276
|
function notificationSuccess() {
|
|
204
277
|
if (reactNative.Platform.OS === "web") return;
|
|
205
|
-
getHaptics().then((h) =>
|
|
278
|
+
getHaptics().then((h) => {
|
|
279
|
+
if (h) {
|
|
280
|
+
h.notificationAsync(h.NotificationFeedbackType.Success);
|
|
281
|
+
} else {
|
|
282
|
+
getPulsar()?.Presets.System.notificationSuccess();
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function notificationError() {
|
|
287
|
+
if (reactNative.Platform.OS === "web") return;
|
|
288
|
+
getHaptics().then((h) => {
|
|
289
|
+
if (h) {
|
|
290
|
+
h.notificationAsync(h.NotificationFeedbackType.Error);
|
|
291
|
+
} else {
|
|
292
|
+
getPulsar()?.Presets.System.notificationError();
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function notificationWarning() {
|
|
297
|
+
if (reactNative.Platform.OS === "web") return;
|
|
298
|
+
getHaptics().then((h) => {
|
|
299
|
+
if (h) {
|
|
300
|
+
h.notificationAsync(h.NotificationFeedbackType.Warning);
|
|
301
|
+
} else {
|
|
302
|
+
getPulsar()?.Presets.System.notificationWarning();
|
|
303
|
+
}
|
|
304
|
+
});
|
|
206
305
|
}
|
|
306
|
+
var richHaptics = {
|
|
307
|
+
/** Hammer strike — strong confirmation feedback. */
|
|
308
|
+
hammer: () => {
|
|
309
|
+
if (reactNative.Platform.OS === "web") return;
|
|
310
|
+
const p = getPulsar();
|
|
311
|
+
if (p) p.Presets.hammer();
|
|
312
|
+
else impactHeavy();
|
|
313
|
+
},
|
|
314
|
+
/** Pulse — rhythmic feedback for toggles or state changes. */
|
|
315
|
+
pulse: () => {
|
|
316
|
+
if (reactNative.Platform.OS === "web") return;
|
|
317
|
+
const p = getPulsar();
|
|
318
|
+
if (p) p.Presets.pulse();
|
|
319
|
+
else selectionAsync();
|
|
320
|
+
},
|
|
321
|
+
/** Buzz — continuous vibration for attention. */
|
|
322
|
+
buzz: () => {
|
|
323
|
+
if (reactNative.Platform.OS === "web") return;
|
|
324
|
+
const p = getPulsar();
|
|
325
|
+
if (p) p.Presets.buzz();
|
|
326
|
+
else impactMedium();
|
|
327
|
+
},
|
|
328
|
+
/** Flick — crisp click feedback. */
|
|
329
|
+
flick: () => {
|
|
330
|
+
if (reactNative.Platform.OS === "web") return;
|
|
331
|
+
const p = getPulsar();
|
|
332
|
+
if (p) p.Presets.flick();
|
|
333
|
+
else selectionAsync();
|
|
334
|
+
},
|
|
335
|
+
/** Soft — gentle, subtle feedback. */
|
|
336
|
+
soft: () => {
|
|
337
|
+
if (reactNative.Platform.OS === "web") return;
|
|
338
|
+
const p = getPulsar();
|
|
339
|
+
if (p) p.Presets.System.impactSoft();
|
|
340
|
+
else impactLight();
|
|
341
|
+
},
|
|
342
|
+
/** Rigid — firm, solid feedback. */
|
|
343
|
+
rigid: () => {
|
|
344
|
+
if (reactNative.Platform.OS === "web") return;
|
|
345
|
+
const p = getPulsar();
|
|
346
|
+
if (p) p.Presets.System.impactRigid();
|
|
347
|
+
else impactMedium();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
207
350
|
var isWeb = reactNative.Platform.OS === "web";
|
|
208
351
|
var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
|
|
209
352
|
var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
|
|
@@ -250,10 +393,10 @@ function Icon({ name, size, color, family }) {
|
|
|
250
393
|
}
|
|
251
394
|
if (!resolved) return null;
|
|
252
395
|
const Component = resolved.component;
|
|
253
|
-
return
|
|
396
|
+
return React25__default.default.createElement(Component, { name, size, color });
|
|
254
397
|
}
|
|
255
398
|
function renderIcon(name, size, color) {
|
|
256
|
-
return
|
|
399
|
+
return React25__default.default.createElement(Icon, { name, size, color });
|
|
257
400
|
}
|
|
258
401
|
|
|
259
402
|
// src/tokens.ts
|
|
@@ -453,10 +596,7 @@ var SPRINGS = {
|
|
|
453
596
|
surfacePressIn: { stiffness: 380, damping: 30, mass: 0.95 },
|
|
454
597
|
surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 },
|
|
455
598
|
/** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
|
|
456
|
-
glide: { stiffness: 380, damping: 38, mass: 1 }
|
|
457
|
-
/** Elastic indicator — Switch thumb, RadioGroup dot. */
|
|
458
|
-
elastic: { stiffness: 320, damping: 22, mass: 0.7 }
|
|
459
|
-
};
|
|
599
|
+
glide: { stiffness: 380, damping: 38, mass: 1 }};
|
|
460
600
|
var TIMINGS = {
|
|
461
601
|
/** Color/opacity transitions on toggles, checkboxes, switches. */
|
|
462
602
|
state: { duration: 160 },
|
|
@@ -471,11 +611,27 @@ var TIMINGS = {
|
|
|
471
611
|
};
|
|
472
612
|
var EASINGS = {
|
|
473
613
|
/** Material-style ease-out — natural deceleration for state changes. */
|
|
474
|
-
standard:
|
|
614
|
+
standard: Animated13.Easing.bezier(0.2, 0, 0, 1),
|
|
475
615
|
/** Strong ease-out for expanding surfaces (Accordion open). */
|
|
476
|
-
expand:
|
|
616
|
+
expand: Animated13.Easing.bezier(0.23, 1, 0.32, 1),
|
|
477
617
|
/** Quick ease-in for collapsing. */
|
|
478
|
-
collapse:
|
|
618
|
+
collapse: Animated13.Easing.in(Animated13.Easing.ease)
|
|
619
|
+
};
|
|
620
|
+
var COLOR_TRANSITION = {
|
|
621
|
+
type: "timing",
|
|
622
|
+
duration: TIMINGS.state.duration,
|
|
623
|
+
easing: [0.2, 0, 0, 1]
|
|
624
|
+
};
|
|
625
|
+
var OPACITY_TRANSITION = {
|
|
626
|
+
type: "timing",
|
|
627
|
+
duration: TIMINGS.state.duration,
|
|
628
|
+
easing: [0.2, 0, 0, 1]
|
|
629
|
+
};
|
|
630
|
+
var SPRING_ELASTIC = {
|
|
631
|
+
type: "spring",
|
|
632
|
+
stiffness: 320,
|
|
633
|
+
damping: 22,
|
|
634
|
+
mass: 0.7
|
|
479
635
|
};
|
|
480
636
|
var PRESS_SCALE = {
|
|
481
637
|
button: 0.95,
|
|
@@ -483,51 +639,36 @@ var PRESS_SCALE = {
|
|
|
483
639
|
row: 0.97,
|
|
484
640
|
chip: 0.94
|
|
485
641
|
};
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if (disabled) return;
|
|
512
|
-
scale2.value = Animated9.withSpring(1, pressOutSpring);
|
|
513
|
-
}, [disabled, pressOutSpring, scale2]);
|
|
514
|
-
const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
|
|
515
|
-
const animatedStyle = Animated9.useAnimatedStyle(() => ({
|
|
516
|
-
transform: [
|
|
517
|
-
{ scale: scale2.value * (hoverActive ? hoverScale : 1) }
|
|
518
|
-
]
|
|
519
|
-
}));
|
|
520
|
-
return {
|
|
521
|
-
animatedStyle,
|
|
522
|
-
onPressIn,
|
|
523
|
-
onPressOut,
|
|
524
|
-
hoverHandlers
|
|
525
|
-
};
|
|
526
|
-
}
|
|
642
|
+
var PressableButton = pressto.createAnimatedPressable((progress) => {
|
|
643
|
+
"worklet";
|
|
644
|
+
const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
|
|
645
|
+
return { transform: [{ scale: scale2 }] };
|
|
646
|
+
});
|
|
647
|
+
var PressableCard = pressto.createAnimatedPressable((progress) => {
|
|
648
|
+
"worklet";
|
|
649
|
+
const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
|
|
650
|
+
return { transform: [{ scale: scale2 }] };
|
|
651
|
+
});
|
|
652
|
+
var PressableRow = pressto.createAnimatedPressable((progress) => {
|
|
653
|
+
"worklet";
|
|
654
|
+
const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
|
|
655
|
+
return { transform: [{ scale: scale2 }] };
|
|
656
|
+
});
|
|
657
|
+
var PressableChip = pressto.createAnimatedPressable((progress) => {
|
|
658
|
+
"worklet";
|
|
659
|
+
const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
|
|
660
|
+
return { transform: [{ scale: scale2 }] };
|
|
661
|
+
});
|
|
662
|
+
var PressableTab = pressto.createAnimatedPressable((progress) => {
|
|
663
|
+
"worklet";
|
|
664
|
+
const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
|
|
665
|
+
return { transform: [{ scale: scale2 }] };
|
|
666
|
+
});
|
|
527
667
|
|
|
528
668
|
// src/components/Button/Button.tsx
|
|
529
669
|
var containerSizeStyles = {
|
|
530
|
-
|
|
670
|
+
// AUDIT FIX: sm was 40pt — below Apple HIG 44pt minimum touch target.
|
|
671
|
+
sm: { paddingHorizontal: s(16), paddingVertical: vs(12), minHeight: 44 },
|
|
531
672
|
md: { paddingHorizontal: s(24), paddingVertical: vs(14), minHeight: 48 },
|
|
532
673
|
lg: { paddingHorizontal: s(28), paddingVertical: vs(16), minHeight: 56 }
|
|
533
674
|
};
|
|
@@ -551,18 +692,13 @@ function ButtonBase({
|
|
|
551
692
|
style,
|
|
552
693
|
onPress,
|
|
553
694
|
accessibilityLabel,
|
|
554
|
-
accessibilityHint
|
|
555
|
-
...props
|
|
695
|
+
accessibilityHint
|
|
556
696
|
}) {
|
|
557
697
|
const { colors } = useTheme();
|
|
558
698
|
const isDisabled = disabled || loading;
|
|
559
|
-
const
|
|
560
|
-
pressScale: PRESS_SCALE.button,
|
|
561
|
-
disabled: isDisabled
|
|
562
|
-
});
|
|
563
|
-
const handlePress = (e) => {
|
|
699
|
+
const handlePress = () => {
|
|
564
700
|
impactMedium();
|
|
565
|
-
onPress?.(
|
|
701
|
+
onPress?.();
|
|
566
702
|
};
|
|
567
703
|
const containerVariantStyle = {
|
|
568
704
|
primary: { backgroundColor: colors.primary },
|
|
@@ -585,56 +721,47 @@ function ButtonBase({
|
|
|
585
721
|
const styleArray = Array.isArray(style) ? style : style ? [style] : [];
|
|
586
722
|
const flatStyle = reactNative.StyleSheet.flatten(styleArray);
|
|
587
723
|
const { flex, ...restStyle } = flatStyle || {};
|
|
588
|
-
return /* @__PURE__ */
|
|
589
|
-
|
|
724
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [fullWidth && styles.fullWidth, flex !== void 0 && { flex }] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
725
|
+
PressableButton,
|
|
590
726
|
{
|
|
591
|
-
style: [
|
|
592
|
-
|
|
727
|
+
style: [
|
|
728
|
+
styles.base,
|
|
729
|
+
containerVariantStyle,
|
|
730
|
+
containerSizeStyles[size],
|
|
731
|
+
fullWidth && styles.fullWidth,
|
|
732
|
+
isDisabled && styles.disabled,
|
|
733
|
+
restStyle
|
|
734
|
+
],
|
|
735
|
+
enabled: !isDisabled,
|
|
736
|
+
onPress: handlePress,
|
|
737
|
+
rippleColor: "transparent",
|
|
738
|
+
touchSoundDisabled: true,
|
|
739
|
+
activateOnHover: true,
|
|
740
|
+
accessibilityRole: "button",
|
|
741
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
742
|
+
accessibilityHint,
|
|
743
|
+
accessibilityState: { disabled: isDisabled, busy: loading }
|
|
593
744
|
},
|
|
594
|
-
/* @__PURE__ */
|
|
595
|
-
reactNative.
|
|
745
|
+
loading ? /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React25__default.default.createElement(
|
|
746
|
+
reactNative.Text,
|
|
596
747
|
{
|
|
597
|
-
style: [
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
containerSizeStyles[size],
|
|
601
|
-
fullWidth && styles.fullWidth,
|
|
602
|
-
isDisabled && styles.disabled,
|
|
603
|
-
restStyle
|
|
604
|
-
],
|
|
605
|
-
disabled: isDisabled,
|
|
606
|
-
activeOpacity: 1,
|
|
607
|
-
touchSoundDisabled: true,
|
|
608
|
-
onPress: handlePress,
|
|
609
|
-
onPressIn,
|
|
610
|
-
onPressOut,
|
|
611
|
-
accessibilityRole: "button",
|
|
612
|
-
accessibilityLabel: accessibilityLabel ?? label,
|
|
613
|
-
accessibilityHint,
|
|
614
|
-
accessibilityState: { disabled: isDisabled, busy: loading },
|
|
615
|
-
...props
|
|
748
|
+
style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
|
|
749
|
+
allowFontScaling: true,
|
|
750
|
+
numberOfLines: 1
|
|
616
751
|
},
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
|
|
629
|
-
allowFontScaling: true,
|
|
630
|
-
numberOfLines: 1
|
|
631
|
-
},
|
|
632
|
-
label
|
|
633
|
-
), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, effectiveIcon))
|
|
634
|
-
)
|
|
635
|
-
);
|
|
752
|
+
label
|
|
753
|
+
)) : /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React25__default.default.createElement(
|
|
754
|
+
reactNative.Text,
|
|
755
|
+
{
|
|
756
|
+
style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
|
|
757
|
+
allowFontScaling: true,
|
|
758
|
+
numberOfLines: 1
|
|
759
|
+
},
|
|
760
|
+
label
|
|
761
|
+
), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon))
|
|
762
|
+
));
|
|
636
763
|
}
|
|
637
|
-
var Button =
|
|
764
|
+
var Button = React25__default.default.memo(ButtonBase);
|
|
638
765
|
var styles = reactNative.StyleSheet.create({
|
|
639
766
|
base: {
|
|
640
767
|
borderRadius: RADIUS.md,
|
|
@@ -660,7 +787,7 @@ var styles = reactNative.StyleSheet.create({
|
|
|
660
787
|
}
|
|
661
788
|
});
|
|
662
789
|
function ButtonGroup({ children, gap = 12, vertical = false, style }) {
|
|
663
|
-
return /* @__PURE__ */
|
|
790
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
664
791
|
reactNative.View,
|
|
665
792
|
{
|
|
666
793
|
style: [
|
|
@@ -670,8 +797,8 @@ function ButtonGroup({ children, gap = 12, vertical = false, style }) {
|
|
|
670
797
|
style
|
|
671
798
|
]
|
|
672
799
|
},
|
|
673
|
-
|
|
674
|
-
if (!
|
|
800
|
+
React25__default.default.Children.map(children, (child) => {
|
|
801
|
+
if (!React25__default.default.isValidElement(child)) return child;
|
|
675
802
|
const childProps = child.props;
|
|
676
803
|
const extraProps = {
|
|
677
804
|
style: [child.props.style, { flex: 1 }]
|
|
@@ -679,7 +806,7 @@ function ButtonGroup({ children, gap = 12, vertical = false, style }) {
|
|
|
679
806
|
if (!vertical && "label" in childProps && childProps["size"] === void 0) {
|
|
680
807
|
extraProps["size"] = "sm";
|
|
681
808
|
}
|
|
682
|
-
return
|
|
809
|
+
return React25__default.default.cloneElement(child, extraProps);
|
|
683
810
|
})
|
|
684
811
|
);
|
|
685
812
|
}
|
|
@@ -695,7 +822,8 @@ var styles2 = reactNative.StyleSheet.create({
|
|
|
695
822
|
}
|
|
696
823
|
});
|
|
697
824
|
var sizeMap = {
|
|
698
|
-
|
|
825
|
+
// AUDIT FIX: sm was 32pt — below Apple HIG 44pt minimum touch target.
|
|
826
|
+
sm: { container: s(44), icon: 18 },
|
|
699
827
|
md: { container: s(44), icon: 20 },
|
|
700
828
|
lg: { container: s(52), icon: 24 }
|
|
701
829
|
};
|
|
@@ -711,18 +839,13 @@ function IconButtonBase({
|
|
|
711
839
|
style,
|
|
712
840
|
onPress,
|
|
713
841
|
accessibilityLabel,
|
|
714
|
-
accessibilityHint
|
|
715
|
-
...props
|
|
842
|
+
accessibilityHint
|
|
716
843
|
}) {
|
|
717
844
|
const { colors } = useTheme();
|
|
718
845
|
const isDisabled = disabled || loading;
|
|
719
|
-
const
|
|
720
|
-
pressScale: PRESS_SCALE.button,
|
|
721
|
-
disabled: isDisabled
|
|
722
|
-
});
|
|
723
|
-
const handlePress = (e) => {
|
|
846
|
+
const handlePress = () => {
|
|
724
847
|
impactLight();
|
|
725
|
-
onPress?.(
|
|
848
|
+
onPress?.();
|
|
726
849
|
};
|
|
727
850
|
const containerVariantStyle = {
|
|
728
851
|
primary: { backgroundColor: colors.primary },
|
|
@@ -744,44 +867,34 @@ function IconButtonBase({
|
|
|
744
867
|
const showBadge = badge !== void 0 && badge !== false && badge !== 0;
|
|
745
868
|
const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
|
|
746
869
|
const showCount = typeof badge === "number" && badge > 0;
|
|
747
|
-
return /* @__PURE__ */
|
|
748
|
-
|
|
870
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles3.wrapper }, /* @__PURE__ */ React25__default.default.createElement(
|
|
871
|
+
PressableButton,
|
|
749
872
|
{
|
|
750
|
-
style: [
|
|
751
|
-
|
|
873
|
+
style: [
|
|
874
|
+
styles3.base,
|
|
875
|
+
containerVariantStyle,
|
|
876
|
+
{ width: containerSize, height: containerSize },
|
|
877
|
+
isDisabled && styles3.disabled,
|
|
878
|
+
style
|
|
879
|
+
],
|
|
880
|
+
enabled: !isDisabled,
|
|
881
|
+
onPress: handlePress,
|
|
882
|
+
rippleColor: "transparent",
|
|
883
|
+
touchSoundDisabled: true,
|
|
884
|
+
activateOnHover: true,
|
|
885
|
+
accessibilityRole: "button",
|
|
886
|
+
accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
|
|
887
|
+
accessibilityHint,
|
|
888
|
+
accessibilityState: { disabled: isDisabled, busy: loading }
|
|
752
889
|
},
|
|
753
|
-
/* @__PURE__ */
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
{ width: containerSize, height: containerSize },
|
|
760
|
-
isDisabled && styles3.disabled,
|
|
761
|
-
style
|
|
762
|
-
],
|
|
763
|
-
disabled: isDisabled,
|
|
764
|
-
activeOpacity: 1,
|
|
765
|
-
touchSoundDisabled: true,
|
|
766
|
-
onPress: handlePress,
|
|
767
|
-
onPressIn,
|
|
768
|
-
onPressOut,
|
|
769
|
-
accessibilityRole: "button",
|
|
770
|
-
accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
|
|
771
|
-
accessibilityHint,
|
|
772
|
-
accessibilityState: { disabled: isDisabled, busy: loading },
|
|
773
|
-
...props
|
|
774
|
-
},
|
|
775
|
-
loading ? /* @__PURE__ */ React26__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
|
|
776
|
-
),
|
|
777
|
-
showBadge && /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [
|
|
778
|
-
styles3.badge,
|
|
779
|
-
{ backgroundColor: colors.primary },
|
|
780
|
-
showCount ? styles3.badgeCount : styles3.badgeDot
|
|
781
|
-
] }, showCount && /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles3.badgeText, { color: colors.primaryForeground }] }, badgeCount))
|
|
782
|
-
);
|
|
890
|
+
loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
|
|
891
|
+
), showBadge && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [
|
|
892
|
+
styles3.badge,
|
|
893
|
+
{ backgroundColor: colors.primary },
|
|
894
|
+
showCount ? styles3.badgeCount : styles3.badgeDot
|
|
895
|
+
] }, showCount && /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.badgeText, { color: colors.primaryForeground }] }, badgeCount)));
|
|
783
896
|
}
|
|
784
|
-
var IconButton =
|
|
897
|
+
var IconButton = React25__default.default.memo(IconButtonBase);
|
|
785
898
|
var styles3 = reactNative.StyleSheet.create({
|
|
786
899
|
wrapper: {
|
|
787
900
|
alignSelf: "flex-start"
|
|
@@ -818,6 +931,22 @@ var styles3 = reactNative.StyleSheet.create({
|
|
|
818
931
|
lineHeight: 14
|
|
819
932
|
}
|
|
820
933
|
});
|
|
934
|
+
var warned = false;
|
|
935
|
+
function warnIfFontsMissing() {
|
|
936
|
+
if (warned) return;
|
|
937
|
+
if (typeof __DEV__ !== "undefined" && !__DEV__) return;
|
|
938
|
+
warned = true;
|
|
939
|
+
try {
|
|
940
|
+
if (!expoFont.isLoaded("Sohne-Regular")) {
|
|
941
|
+
console.warn(
|
|
942
|
+
"[retray-ui-kit] Sohne fonts are not loaded \u2014 text will fall back to the system font. Load them at your app root before rendering any UI kit component:\n\n import { useFonts } from 'expo-font'\n import { SohneFonts } from '@retray-dev/ui-kit/fonts'\n\n const [fontsLoaded] = useFonts(SohneFonts)\n if (!fontsLoaded) return null\n"
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
} catch {
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// src/components/Text/Text.tsx
|
|
821
950
|
var variantStyles = {
|
|
822
951
|
"display-hero": { ...TYPOGRAPHY["display-hero"], fontSize: ms(TYPOGRAPHY["display-hero"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-hero"].lineHeight) },
|
|
823
952
|
"display-xl": { ...TYPOGRAPHY["display-xl"], fontSize: ms(TYPOGRAPHY["display-xl"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-xl"].lineHeight) },
|
|
@@ -856,10 +985,11 @@ var defaultColorVariant = {
|
|
|
856
985
|
"button-sm": "foreground"
|
|
857
986
|
};
|
|
858
987
|
function TextBase({ variant = "body-md", color, style, children, ...props }) {
|
|
988
|
+
warnIfFontsMissing();
|
|
859
989
|
const { colors } = useTheme();
|
|
860
990
|
const colorKey = defaultColorVariant[variant] ?? "foreground";
|
|
861
991
|
const resolvedColor = color ?? colors[colorKey];
|
|
862
|
-
return /* @__PURE__ */
|
|
992
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
863
993
|
reactNative.Text,
|
|
864
994
|
{
|
|
865
995
|
style: [variantStyles[variant], { color: resolvedColor }, style],
|
|
@@ -869,12 +999,12 @@ function TextBase({ variant = "body-md", color, style, children, ...props }) {
|
|
|
869
999
|
children
|
|
870
1000
|
);
|
|
871
1001
|
}
|
|
872
|
-
var Text3 =
|
|
1002
|
+
var Text3 = React25__default.default.memo(TextBase);
|
|
873
1003
|
function useColorTransition(active, options = {}) {
|
|
874
1004
|
const { duration = TIMINGS.state.duration } = options;
|
|
875
|
-
const progress =
|
|
876
|
-
|
|
877
|
-
progress.value =
|
|
1005
|
+
const progress = Animated13.useSharedValue(active ? 1 : 0);
|
|
1006
|
+
React25.useEffect(() => {
|
|
1007
|
+
progress.value = Animated13.withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard });
|
|
878
1008
|
}, [active, duration, progress]);
|
|
879
1009
|
return progress;
|
|
880
1010
|
}
|
|
@@ -883,8 +1013,8 @@ function useColorTransition(active, options = {}) {
|
|
|
883
1013
|
var webInputResetStyle = reactNative.Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
|
|
884
1014
|
function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
|
|
885
1015
|
const { colors } = useTheme();
|
|
886
|
-
const [focused, setFocused] =
|
|
887
|
-
const [showPassword, setShowPassword] =
|
|
1016
|
+
const [focused, setFocused] = React25.useState(false);
|
|
1017
|
+
const [showPassword, setShowPassword] = React25.useState(false);
|
|
888
1018
|
const focusProgress = useColorTransition(focused, {
|
|
889
1019
|
duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
|
|
890
1020
|
});
|
|
@@ -892,7 +1022,7 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
892
1022
|
const isPassword = type === "password";
|
|
893
1023
|
const effectiveSecure = isPassword ? !showPassword : secureTextEntry;
|
|
894
1024
|
const effectivePrefix = prefixIcon ? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.foregroundMuted) : prefix;
|
|
895
|
-
const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */
|
|
1025
|
+
const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React25__default.default.createElement(
|
|
896
1026
|
reactNative.TouchableOpacity,
|
|
897
1027
|
{
|
|
898
1028
|
onPress: () => setShowPassword(!showPassword),
|
|
@@ -901,14 +1031,14 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
901
1031
|
accessibilityRole: "button",
|
|
902
1032
|
accessibilityLabel: showPassword ? "Hide password" : "Show password"
|
|
903
1033
|
},
|
|
904
|
-
/* @__PURE__ */
|
|
1034
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.foregroundMuted })
|
|
905
1035
|
) : suffixIcon ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted) : suffix;
|
|
906
|
-
const borderAnimStyle =
|
|
907
|
-
borderColor: error ? colors.destructive :
|
|
908
|
-
borderWidth: error ? 2 :
|
|
1036
|
+
const borderAnimStyle = Animated13.useAnimatedStyle(() => ({
|
|
1037
|
+
borderColor: error ? colors.destructive : Animated13.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
|
|
1038
|
+
borderWidth: error ? 2 : Animated13.interpolate(focusProgress.value, [0, 1], [1, 2])
|
|
909
1039
|
}));
|
|
910
|
-
return /* @__PURE__ */
|
|
911
|
-
|
|
1040
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles4.container, isDisabled && styles4.containerDisabled, containerStyle] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React25__default.default.createElement(
|
|
1041
|
+
Animated13__default.default.View,
|
|
912
1042
|
{
|
|
913
1043
|
style: [
|
|
914
1044
|
styles4.inputWrapper,
|
|
@@ -916,9 +1046,9 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
916
1046
|
inputWrapperStyle
|
|
917
1047
|
]
|
|
918
1048
|
},
|
|
919
|
-
/* @__PURE__ */
|
|
920
|
-
effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */
|
|
921
|
-
/* @__PURE__ */
|
|
1049
|
+
/* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles4.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
|
|
1050
|
+
effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.prefixText, { color: colors.foregroundMuted }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles4.prefixContainer }, effectivePrefix) : null,
|
|
1051
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
922
1052
|
reactNative.TextInput,
|
|
923
1053
|
{
|
|
924
1054
|
style: [
|
|
@@ -943,8 +1073,8 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
943
1073
|
...props
|
|
944
1074
|
}
|
|
945
1075
|
),
|
|
946
|
-
effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */
|
|
947
|
-
), error ? /* @__PURE__ */
|
|
1076
|
+
effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.suffixText, { color: colors.foregroundMuted }, suffixStyle], allowFontScaling: true }, effectiveSuffix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles4.suffixContainer }, effectiveSuffix) : null
|
|
1077
|
+
), error ? /* @__PURE__ */ React25__default.default.createElement(
|
|
948
1078
|
reactNative.Text,
|
|
949
1079
|
{
|
|
950
1080
|
style: [styles4.helperText, { color: colors.destructive }],
|
|
@@ -952,7 +1082,7 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
952
1082
|
accessibilityLiveRegion: "polite"
|
|
953
1083
|
},
|
|
954
1084
|
error
|
|
955
|
-
) : null, !error && hint ? /* @__PURE__ */
|
|
1085
|
+
) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
|
|
956
1086
|
}
|
|
957
1087
|
var styles4 = reactNative.StyleSheet.create({
|
|
958
1088
|
container: {
|
|
@@ -1055,9 +1185,19 @@ function BadgeBase({ label, children, variant = "default", size = "md", icon, ic
|
|
|
1055
1185
|
}[variant];
|
|
1056
1186
|
const effectiveIcon = iconName ? renderIcon(iconName, sizeIconSize[size], iconColor ?? textColor) : icon;
|
|
1057
1187
|
const content = children ?? label;
|
|
1058
|
-
|
|
1188
|
+
const a11yLabel = typeof content === "string" ? content : label;
|
|
1189
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1190
|
+
reactNative.View,
|
|
1191
|
+
{
|
|
1192
|
+
style: [styles5.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style],
|
|
1193
|
+
accessibilityRole: "text",
|
|
1194
|
+
accessibilityLabel: a11yLabel
|
|
1195
|
+
},
|
|
1196
|
+
effectiveIcon,
|
|
1197
|
+
typeof content === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles5.label, { color: textColor }, sizeFontSize[size]], allowFontScaling: true }, content) : content
|
|
1198
|
+
);
|
|
1059
1199
|
}
|
|
1060
|
-
var Badge =
|
|
1200
|
+
var Badge = React25__default.default.memo(BadgeBase);
|
|
1061
1201
|
var styles5 = reactNative.StyleSheet.create({
|
|
1062
1202
|
container: {
|
|
1063
1203
|
borderRadius: 9999,
|
|
@@ -1071,12 +1211,6 @@ var styles5 = reactNative.StyleSheet.create({
|
|
|
1071
1211
|
});
|
|
1072
1212
|
function Card({ children, variant = "elevated", onPress, style, accessibilityLabel }) {
|
|
1073
1213
|
const { colors } = useTheme();
|
|
1074
|
-
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
1075
|
-
pressScale: PRESS_SCALE.card,
|
|
1076
|
-
pressInSpring: SPRINGS.surfacePressIn,
|
|
1077
|
-
pressOutSpring: SPRINGS.surfacePressOut,
|
|
1078
|
-
disabled: !onPress
|
|
1079
|
-
});
|
|
1080
1214
|
const handlePress = () => {
|
|
1081
1215
|
if (!onPress) return;
|
|
1082
1216
|
impactLight();
|
|
@@ -1108,40 +1242,39 @@ function Card({ children, variant = "elevated", onPress, style, accessibilityLab
|
|
|
1108
1242
|
elevation: 0
|
|
1109
1243
|
}
|
|
1110
1244
|
}[variant];
|
|
1111
|
-
const cardContent = /* @__PURE__ */
|
|
1245
|
+
const cardContent = /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.card, variantStyle, style] }, children);
|
|
1112
1246
|
if (onPress) {
|
|
1113
|
-
return /* @__PURE__ */
|
|
1114
|
-
|
|
1247
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1248
|
+
PressableCard,
|
|
1115
1249
|
{
|
|
1116
1250
|
onPress: handlePress,
|
|
1117
|
-
|
|
1118
|
-
onPressOut,
|
|
1119
|
-
activeOpacity: 1,
|
|
1251
|
+
rippleColor: "transparent",
|
|
1120
1252
|
touchSoundDisabled: true,
|
|
1253
|
+
activateOnHover: true,
|
|
1121
1254
|
accessibilityRole: "button",
|
|
1122
1255
|
accessibilityLabel
|
|
1123
1256
|
},
|
|
1124
1257
|
cardContent
|
|
1125
|
-
)
|
|
1258
|
+
);
|
|
1126
1259
|
}
|
|
1127
1260
|
return cardContent;
|
|
1128
1261
|
}
|
|
1129
1262
|
function CardHeader({ children, style }) {
|
|
1130
|
-
return /* @__PURE__ */
|
|
1263
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.header, style] }, children);
|
|
1131
1264
|
}
|
|
1132
1265
|
function CardTitle({ children, style }) {
|
|
1133
1266
|
const { colors } = useTheme();
|
|
1134
|
-
return /* @__PURE__ */
|
|
1267
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles6.title, { color: colors.foreground }, style], allowFontScaling: true }, children);
|
|
1135
1268
|
}
|
|
1136
1269
|
function CardDescription({ children, style }) {
|
|
1137
1270
|
const { colors } = useTheme();
|
|
1138
|
-
return /* @__PURE__ */
|
|
1271
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles6.description, { color: colors.foregroundSubtle }, style], allowFontScaling: true }, children);
|
|
1139
1272
|
}
|
|
1140
1273
|
function CardContent({ children, style }) {
|
|
1141
|
-
return /* @__PURE__ */
|
|
1274
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.content, style] }, children);
|
|
1142
1275
|
}
|
|
1143
1276
|
function CardFooter({ children, style }) {
|
|
1144
|
-
return /* @__PURE__ */
|
|
1277
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.footer, style] }, children);
|
|
1145
1278
|
}
|
|
1146
1279
|
var styles6 = reactNative.StyleSheet.create({
|
|
1147
1280
|
card: {
|
|
@@ -1179,7 +1312,7 @@ var styles6 = reactNative.StyleSheet.create({
|
|
|
1179
1312
|
});
|
|
1180
1313
|
function Separator({ orientation = "horizontal", style }) {
|
|
1181
1314
|
const { colors } = useTheme();
|
|
1182
|
-
return /* @__PURE__ */
|
|
1315
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1183
1316
|
reactNative.View,
|
|
1184
1317
|
{
|
|
1185
1318
|
style: [
|
|
@@ -1212,17 +1345,38 @@ var labelFontSize = {
|
|
|
1212
1345
|
};
|
|
1213
1346
|
function Spinner({ size = "md", color, label, ...props }) {
|
|
1214
1347
|
const { colors } = useTheme();
|
|
1348
|
+
const a11yLabel = label || "Loading";
|
|
1215
1349
|
if (label) {
|
|
1216
|
-
return /* @__PURE__ */
|
|
1217
|
-
reactNative.
|
|
1350
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1351
|
+
reactNative.View,
|
|
1218
1352
|
{
|
|
1219
|
-
style:
|
|
1220
|
-
|
|
1353
|
+
style: styles8.wrapper,
|
|
1354
|
+
accessibilityRole: "progressbar",
|
|
1355
|
+
accessibilityLabel: a11yLabel,
|
|
1356
|
+
accessibilityState: { busy: true }
|
|
1221
1357
|
},
|
|
1222
|
-
|
|
1223
|
-
|
|
1358
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: sizeMap2[size], color: color ?? colors.primary, ...props }),
|
|
1359
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
1360
|
+
reactNative.Text,
|
|
1361
|
+
{
|
|
1362
|
+
style: [styles8.label, { color: colors.foregroundMuted, fontSize: labelFontSize[size] }],
|
|
1363
|
+
allowFontScaling: true
|
|
1364
|
+
},
|
|
1365
|
+
label
|
|
1366
|
+
)
|
|
1367
|
+
);
|
|
1224
1368
|
}
|
|
1225
|
-
return /* @__PURE__ */
|
|
1369
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1370
|
+
reactNative.ActivityIndicator,
|
|
1371
|
+
{
|
|
1372
|
+
size: sizeMap2[size],
|
|
1373
|
+
color: color ?? colors.primary,
|
|
1374
|
+
accessibilityRole: "progressbar",
|
|
1375
|
+
accessibilityLabel: a11yLabel,
|
|
1376
|
+
accessibilityState: { busy: true },
|
|
1377
|
+
...props
|
|
1378
|
+
}
|
|
1379
|
+
);
|
|
1226
1380
|
}
|
|
1227
1381
|
var styles8 = reactNative.StyleSheet.create({
|
|
1228
1382
|
wrapper: {
|
|
@@ -1243,23 +1397,23 @@ function Skeleton({
|
|
|
1243
1397
|
style
|
|
1244
1398
|
}) {
|
|
1245
1399
|
const { colors, colorScheme } = useTheme();
|
|
1246
|
-
const shimmer =
|
|
1247
|
-
const [containerWidth, setContainerWidth] =
|
|
1400
|
+
const shimmer = Animated13.useSharedValue(0);
|
|
1401
|
+
const [containerWidth, setContainerWidth] = React25.useState(300);
|
|
1248
1402
|
const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(255,255,255,0.7)";
|
|
1249
|
-
|
|
1250
|
-
shimmer.value =
|
|
1251
|
-
|
|
1403
|
+
React25.useEffect(() => {
|
|
1404
|
+
shimmer.value = Animated13.withRepeat(
|
|
1405
|
+
Animated13.withTiming(1, { duration: TIMINGS.shimmer.duration, easing: Animated13.Easing.linear }),
|
|
1252
1406
|
-1,
|
|
1253
1407
|
false
|
|
1254
1408
|
);
|
|
1255
1409
|
}, [shimmer]);
|
|
1256
|
-
const shimmerStyle =
|
|
1410
|
+
const shimmerStyle = Animated13.useAnimatedStyle(() => ({
|
|
1257
1411
|
transform: [{ translateX: -containerWidth + shimmer.value * (containerWidth * 2) }]
|
|
1258
1412
|
}));
|
|
1259
1413
|
const resolvedWidth = preset === "circle" ? s(diameter) : preset === "text" ? "60%" : width;
|
|
1260
1414
|
const resolvedHeight = preset === "circle" ? s(diameter) : preset === "text" ? 14 : height;
|
|
1261
1415
|
const resolvedRadius = preset === "circle" ? 9999 : preset === "text" ? 4 : borderRadius;
|
|
1262
|
-
return /* @__PURE__ */
|
|
1416
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1263
1417
|
reactNative.View,
|
|
1264
1418
|
{
|
|
1265
1419
|
style: [
|
|
@@ -1272,7 +1426,7 @@ function Skeleton({
|
|
|
1272
1426
|
accessibilityLabel: "Loading",
|
|
1273
1427
|
accessibilityState: { busy: true }
|
|
1274
1428
|
},
|
|
1275
|
-
/* @__PURE__ */
|
|
1429
|
+
/* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [reactNative.StyleSheet.absoluteFill, shimmerStyle] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
1276
1430
|
expoLinearGradient.LinearGradient,
|
|
1277
1431
|
{
|
|
1278
1432
|
colors: ["transparent", shimmerHighlight, "transparent"],
|
|
@@ -1283,11 +1437,66 @@ function Skeleton({
|
|
|
1283
1437
|
))
|
|
1284
1438
|
);
|
|
1285
1439
|
}
|
|
1440
|
+
var aspectRatioMap = {
|
|
1441
|
+
"1:1": 1,
|
|
1442
|
+
"4:3": 3 / 4,
|
|
1443
|
+
"16:9": 9 / 16,
|
|
1444
|
+
"4:5": 5 / 4,
|
|
1445
|
+
"3:2": 2 / 3
|
|
1446
|
+
};
|
|
1447
|
+
function MediaCardSkeleton({ aspectRatio = "4:3", showSubtitle = true, style }) {
|
|
1448
|
+
const ratio = aspectRatioMap[aspectRatio];
|
|
1449
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "100%", height: void 0, style: skeletonStyles.fill, borderRadius: RADIUS.md }))), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: skeletonStyles.meta }, /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "70%", height: vs(14), borderRadius: RADIUS.xs }), showSubtitle ? /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "45%", height: vs(12), borderRadius: RADIUS.xs }) : null));
|
|
1450
|
+
}
|
|
1451
|
+
function ListItemSkeleton({ showAvatar = true, showSubtitle = true, style }) {
|
|
1452
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [skeletonStyles.row, style] }, showAvatar ? /* @__PURE__ */ React25__default.default.createElement(Skeleton, { preset: "circle", diameter: 40 }) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: skeletonStyles.rowText }, /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "60%", height: vs(14), borderRadius: RADIUS.xs }), showSubtitle ? /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "40%", height: vs(12), borderRadius: RADIUS.xs }) : null));
|
|
1453
|
+
}
|
|
1454
|
+
function ListSkeleton({
|
|
1455
|
+
count = 6,
|
|
1456
|
+
columns = 1,
|
|
1457
|
+
gap = 12,
|
|
1458
|
+
aspectRatio = "4:3",
|
|
1459
|
+
showAvatar = true,
|
|
1460
|
+
style
|
|
1461
|
+
}) {
|
|
1462
|
+
if (columns <= 1) {
|
|
1463
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [{ gap: vs(gap) }, style] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React25__default.default.createElement(ListItemSkeleton, { key: i, showAvatar })));
|
|
1464
|
+
}
|
|
1465
|
+
const widthPct = `${100 / columns}%`;
|
|
1466
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [skeletonStyles.grid, { marginHorizontal: -s(gap) / 2 }, style] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: i, style: { width: widthPct, paddingHorizontal: s(gap) / 2, marginBottom: vs(gap) } }, /* @__PURE__ */ React25__default.default.createElement(MediaCardSkeleton, { aspectRatio }))));
|
|
1467
|
+
}
|
|
1468
|
+
Skeleton.MediaCard = MediaCardSkeleton;
|
|
1469
|
+
Skeleton.ListItem = ListItemSkeleton;
|
|
1470
|
+
Skeleton.List = ListSkeleton;
|
|
1286
1471
|
var styles9 = reactNative.StyleSheet.create({
|
|
1287
1472
|
base: {
|
|
1288
1473
|
overflow: "hidden"
|
|
1289
1474
|
}
|
|
1290
1475
|
});
|
|
1476
|
+
var skeletonStyles = reactNative.StyleSheet.create({
|
|
1477
|
+
grid: {
|
|
1478
|
+
flexDirection: "row",
|
|
1479
|
+
flexWrap: "wrap"
|
|
1480
|
+
},
|
|
1481
|
+
fill: {
|
|
1482
|
+
width: "100%",
|
|
1483
|
+
height: "100%"
|
|
1484
|
+
},
|
|
1485
|
+
meta: {
|
|
1486
|
+
paddingTop: vs(8),
|
|
1487
|
+
gap: vs(6)
|
|
1488
|
+
},
|
|
1489
|
+
row: {
|
|
1490
|
+
flexDirection: "row",
|
|
1491
|
+
alignItems: "center",
|
|
1492
|
+
gap: s(12),
|
|
1493
|
+
paddingVertical: vs(8)
|
|
1494
|
+
},
|
|
1495
|
+
rowText: {
|
|
1496
|
+
flex: 1,
|
|
1497
|
+
gap: vs(6)
|
|
1498
|
+
}
|
|
1499
|
+
});
|
|
1291
1500
|
var sizeMap3 = {
|
|
1292
1501
|
sm: s(28),
|
|
1293
1502
|
md: s(40),
|
|
@@ -1317,13 +1526,13 @@ function getInitials(fallback, fallbackText) {
|
|
|
1317
1526
|
}
|
|
1318
1527
|
function AvatarBase({ src, fallback, fallbackText, size = "md", status, style }) {
|
|
1319
1528
|
const { colors } = useTheme();
|
|
1320
|
-
const [imageError, setImageError] =
|
|
1529
|
+
const [imageError, setImageError] = React25.useState(false);
|
|
1321
1530
|
const dimension = typeof size === "number" ? size : sizeMap3[size];
|
|
1322
1531
|
const fontSize = typeof size === "number" ? size * 0.38 : fontSizeMap[size];
|
|
1323
1532
|
const showFallback = !src || imageError;
|
|
1324
1533
|
const statusSize = typeof size === "number" ? size * 0.25 : statusSizeMap[size];
|
|
1325
1534
|
const statusColor = {
|
|
1326
|
-
online:
|
|
1535
|
+
online: colors.success,
|
|
1327
1536
|
offline: "transparent",
|
|
1328
1537
|
busy: colors.destructive,
|
|
1329
1538
|
away: colors.warning
|
|
@@ -1335,38 +1544,48 @@ function AvatarBase({ src, fallback, fallbackText, size = "md", status, style })
|
|
|
1335
1544
|
backgroundColor: colors.surface,
|
|
1336
1545
|
overflow: "hidden"
|
|
1337
1546
|
};
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
{
|
|
1341
|
-
source: { uri: src },
|
|
1342
|
-
style: { width: dimension, height: dimension },
|
|
1343
|
-
onError: () => setImageError(true)
|
|
1344
|
-
}
|
|
1345
|
-
) : /* @__PURE__ */ React26__default.default.createElement(
|
|
1346
|
-
reactNative.Text,
|
|
1347
|
-
{
|
|
1348
|
-
style: [styles10.fallback, { color: colors.foregroundMuted, fontSize }],
|
|
1349
|
-
allowFontScaling: true
|
|
1350
|
-
},
|
|
1351
|
-
getInitials(fallback, fallbackText)
|
|
1352
|
-
)), status && /* @__PURE__ */ React26__default.default.createElement(
|
|
1547
|
+
const a11yLabel = fallbackText || fallback || "Avatar";
|
|
1548
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1353
1549
|
reactNative.View,
|
|
1354
1550
|
{
|
|
1355
|
-
style: [
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1551
|
+
style: [styles10.wrapper, style],
|
|
1552
|
+
accessibilityRole: "image",
|
|
1553
|
+
accessibilityLabel: a11yLabel
|
|
1554
|
+
},
|
|
1555
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles10.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React25__default.default.createElement(
|
|
1556
|
+
reactNative.Image,
|
|
1557
|
+
{
|
|
1558
|
+
source: { uri: src },
|
|
1559
|
+
style: { width: dimension, height: dimension },
|
|
1560
|
+
onError: () => setImageError(true)
|
|
1561
|
+
}
|
|
1562
|
+
) : /* @__PURE__ */ React25__default.default.createElement(
|
|
1563
|
+
reactNative.Text,
|
|
1564
|
+
{
|
|
1565
|
+
style: [styles10.fallback, { color: colors.foregroundMuted, fontSize }],
|
|
1566
|
+
allowFontScaling: true
|
|
1567
|
+
},
|
|
1568
|
+
getInitials(fallback, fallbackText)
|
|
1569
|
+
)),
|
|
1570
|
+
status && /* @__PURE__ */ React25__default.default.createElement(
|
|
1571
|
+
reactNative.View,
|
|
1572
|
+
{
|
|
1573
|
+
style: [
|
|
1574
|
+
styles10.statusDot,
|
|
1575
|
+
{
|
|
1576
|
+
width: statusSize,
|
|
1577
|
+
height: statusSize,
|
|
1578
|
+
borderRadius: statusSize / 2,
|
|
1579
|
+
backgroundColor: statusColor[status],
|
|
1580
|
+
borderWidth: status === "offline" ? 2 : 1.5,
|
|
1581
|
+
borderColor: status === "offline" ? colors.border : colors.background
|
|
1582
|
+
}
|
|
1583
|
+
]
|
|
1584
|
+
}
|
|
1585
|
+
)
|
|
1586
|
+
);
|
|
1368
1587
|
}
|
|
1369
|
-
var Avatar =
|
|
1588
|
+
var Avatar = React25__default.default.memo(AvatarBase);
|
|
1370
1589
|
var styles10 = reactNative.StyleSheet.create({
|
|
1371
1590
|
wrapper: {
|
|
1372
1591
|
alignSelf: "flex-start",
|
|
@@ -1391,24 +1610,27 @@ function AlertBanner({ title, description, variant = "default", icon, iconName,
|
|
|
1391
1610
|
const accentColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : variant === "warning" ? colors.warning : colors.foreground;
|
|
1392
1611
|
const bgColor = variant === "destructive" ? isDark ? "rgba(239, 83, 80, 0.15)" : "rgba(199, 40, 40, 0.10)" : variant === "success" ? isDark ? "rgba(46, 125, 82, 0.15)" : "rgba(26, 122, 69, 0.10)" : variant === "warning" ? isDark ? "rgba(245, 166, 35, 0.15)" : "rgba(154, 82, 0, 0.10)" : colors.surface;
|
|
1393
1612
|
const borderColor = variant === "destructive" ? isDark ? "rgba(239, 83, 80, 0.30)" : "rgba(199, 40, 40, 0.25)" : variant === "success" ? isDark ? "rgba(46, 125, 82, 0.30)" : "rgba(26, 122, 69, 0.25)" : variant === "warning" ? isDark ? "rgba(245, 166, 35, 0.30)" : "rgba(154, 82, 0, 0.25)" : colors.border;
|
|
1394
|
-
const defaultIcon = variant === "success" ? /* @__PURE__ */
|
|
1613
|
+
const defaultIcon = variant === "success" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: ms(16), color: accentColor }) : variant === "destructive" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "error-outline", size: ms(17), color: accentColor }) : variant === "warning" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "warning-amber", size: ms(17), color: accentColor }) : (
|
|
1395
1614
|
// AUDIT FIX: default variant previously used colors.primary (near-black)
|
|
1396
1615
|
// as the info icon tint — ambiguous and heavy. accentResolved gives it
|
|
1397
1616
|
// a meaningful chromatic signal when an accent is defined.
|
|
1398
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: ms(16), color: accentColor })
|
|
1399
1618
|
);
|
|
1400
1619
|
const effectiveIcon = iconName ? renderIcon(iconName, ms(16), iconColor ?? accentColor) : icon ?? defaultIcon;
|
|
1401
|
-
|
|
1620
|
+
const a11yLabel = description ? `${title}. ${description}` : title;
|
|
1621
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1402
1622
|
reactNative.View,
|
|
1403
1623
|
{
|
|
1404
1624
|
style: [
|
|
1405
1625
|
styles11.container,
|
|
1406
1626
|
{ backgroundColor: bgColor, borderWidth: 1, borderColor },
|
|
1407
1627
|
style
|
|
1408
|
-
]
|
|
1628
|
+
],
|
|
1629
|
+
accessibilityRole: "alert",
|
|
1630
|
+
accessibilityLabel: a11yLabel
|
|
1409
1631
|
},
|
|
1410
|
-
/* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1632
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.iconSlot }, effectiveIcon),
|
|
1633
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.description, { color: colors.foreground, opacity: 0.85 }], allowFontScaling: true }, description) : null)
|
|
1412
1634
|
);
|
|
1413
1635
|
}
|
|
1414
1636
|
var styles11 = reactNative.StyleSheet.create({
|
|
@@ -1439,17 +1661,17 @@ var styles11 = reactNative.StyleSheet.create({
|
|
|
1439
1661
|
function Progress({ value = 0, max = 100, variant = "default", style, accessibilityLabel }) {
|
|
1440
1662
|
const { colors } = useTheme();
|
|
1441
1663
|
const percent = Math.min(Math.max(value / max * 100, 0), 100);
|
|
1442
|
-
const [trackWidth, setTrackWidth] =
|
|
1443
|
-
const animatedWidth =
|
|
1444
|
-
|
|
1664
|
+
const [trackWidth, setTrackWidth] = React25.useState(0);
|
|
1665
|
+
const animatedWidth = Animated13.useSharedValue(0);
|
|
1666
|
+
React25.useEffect(() => {
|
|
1445
1667
|
if (trackWidth === 0) return;
|
|
1446
|
-
animatedWidth.value =
|
|
1668
|
+
animatedWidth.value = Animated13.withSpring(percent / 100 * trackWidth, SPRINGS.glide);
|
|
1447
1669
|
}, [percent, trackWidth, animatedWidth]);
|
|
1448
|
-
const indicatorAnimatedStyle =
|
|
1670
|
+
const indicatorAnimatedStyle = Animated13.useAnimatedStyle(() => ({
|
|
1449
1671
|
width: animatedWidth.value
|
|
1450
1672
|
}));
|
|
1451
1673
|
const indicatorColor = variant === "success" ? colors.success : variant === "warning" ? colors.warning : variant === "destructive" ? colors.destructive : colors.primary;
|
|
1452
|
-
return /* @__PURE__ */
|
|
1674
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1453
1675
|
reactNative.View,
|
|
1454
1676
|
{
|
|
1455
1677
|
style: [styles12.track, { backgroundColor: colors.surface }, style],
|
|
@@ -1458,8 +1680,8 @@ function Progress({ value = 0, max = 100, variant = "default", style, accessibil
|
|
|
1458
1680
|
accessibilityLabel,
|
|
1459
1681
|
accessibilityValue: { min: 0, max: 100, now: Math.round(percent) }
|
|
1460
1682
|
},
|
|
1461
|
-
/* @__PURE__ */
|
|
1462
|
-
|
|
1683
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
1684
|
+
Animated13__default.default.View,
|
|
1463
1685
|
{
|
|
1464
1686
|
style: [styles12.indicator, { backgroundColor: indicatorColor }, indicatorAnimatedStyle]
|
|
1465
1687
|
}
|
|
@@ -1482,7 +1704,7 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, act
|
|
|
1482
1704
|
const { colors } = useTheme();
|
|
1483
1705
|
const isCompact = size === "compact";
|
|
1484
1706
|
const effectiveIcon = iconName ? renderIcon(iconName, isCompact ? 32 : 48, iconColor ?? colors.foregroundMuted) : icon;
|
|
1485
|
-
return /* @__PURE__ */
|
|
1707
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
1486
1708
|
reactNative.View,
|
|
1487
1709
|
{
|
|
1488
1710
|
style: [
|
|
@@ -1492,7 +1714,7 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, act
|
|
|
1492
1714
|
style
|
|
1493
1715
|
]
|
|
1494
1716
|
},
|
|
1495
|
-
effectiveIcon ? /* @__PURE__ */
|
|
1717
|
+
effectiveIcon ? /* @__PURE__ */ React25__default.default.createElement(
|
|
1496
1718
|
reactNative.View,
|
|
1497
1719
|
{
|
|
1498
1720
|
style: [
|
|
@@ -1503,15 +1725,15 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, act
|
|
|
1503
1725
|
},
|
|
1504
1726
|
effectiveIcon
|
|
1505
1727
|
) : null,
|
|
1506
|
-
/* @__PURE__ */
|
|
1728
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles13.textWrapper }, /* @__PURE__ */ React25__default.default.createElement(
|
|
1507
1729
|
reactNative.Text,
|
|
1508
1730
|
{
|
|
1509
1731
|
style: [styles13.title, isCompact && styles13.titleCompact, { color: colors.foreground }],
|
|
1510
1732
|
allowFontScaling: true
|
|
1511
1733
|
},
|
|
1512
1734
|
title
|
|
1513
|
-
), description && !isCompact ? /* @__PURE__ */
|
|
1514
|
-
!isCompact && (action ? /* @__PURE__ */
|
|
1735
|
+
), description && !isCompact ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles13.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null),
|
|
1736
|
+
!isCompact && (action ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles13.action }, action) : actionLabel && onAction ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles13.action }, /* @__PURE__ */ React25__default.default.createElement(Button, { label: actionLabel, variant: "primary", onPress: onAction })) : null)
|
|
1515
1737
|
);
|
|
1516
1738
|
}
|
|
1517
1739
|
var styles13 = reactNative.StyleSheet.create({
|
|
@@ -1520,9 +1742,12 @@ var styles13 = reactNative.StyleSheet.create({
|
|
|
1520
1742
|
justifyContent: "center",
|
|
1521
1743
|
borderWidth: 1,
|
|
1522
1744
|
borderStyle: "dashed",
|
|
1523
|
-
borderRadius: ms(12)
|
|
1745
|
+
borderRadius: ms(12),
|
|
1746
|
+
paddingBottom: vs(32)
|
|
1747
|
+
},
|
|
1748
|
+
containerCompact: {
|
|
1749
|
+
paddingBottom: vs(20)
|
|
1524
1750
|
},
|
|
1525
|
-
containerCompact: {},
|
|
1526
1751
|
iconWrapper: {
|
|
1527
1752
|
width: s(80),
|
|
1528
1753
|
height: s(80),
|
|
@@ -1561,7 +1786,6 @@ var styles13 = reactNative.StyleSheet.create({
|
|
|
1561
1786
|
},
|
|
1562
1787
|
action: {
|
|
1563
1788
|
marginTop: vs(8),
|
|
1564
|
-
marginBottom: s(32),
|
|
1565
1789
|
paddingHorizontal: s(32)
|
|
1566
1790
|
}
|
|
1567
1791
|
});
|
|
@@ -1582,26 +1806,26 @@ function Textarea({
|
|
|
1582
1806
|
...props
|
|
1583
1807
|
}) {
|
|
1584
1808
|
const { colors } = useTheme();
|
|
1585
|
-
const [focused, setFocused] =
|
|
1809
|
+
const [focused, setFocused] = React25.useState(false);
|
|
1586
1810
|
const focusProgress = useColorTransition(focused, {
|
|
1587
1811
|
duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
|
|
1588
1812
|
});
|
|
1589
1813
|
const resolvedPrefixIcon = prefixIcon ? renderIcon(prefixIcon, ms(16), prefixIconColor ?? colors.foregroundMuted) : prefixIconNode;
|
|
1590
|
-
const borderAnimStyle =
|
|
1591
|
-
borderColor: error ? colors.destructive :
|
|
1592
|
-
borderWidth: error ? 2 :
|
|
1814
|
+
const borderAnimStyle = Animated13.useAnimatedStyle(() => ({
|
|
1815
|
+
borderColor: error ? colors.destructive : Animated13.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
|
|
1816
|
+
borderWidth: error ? 2 : Animated13.interpolate(focusProgress.value, [0, 1], [1, 2])
|
|
1593
1817
|
}));
|
|
1594
|
-
return /* @__PURE__ */
|
|
1595
|
-
|
|
1818
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles14.container, containerStyle] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles14.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React25__default.default.createElement(
|
|
1819
|
+
Animated13__default.default.View,
|
|
1596
1820
|
{
|
|
1597
1821
|
style: [
|
|
1598
1822
|
styles14.inputWrapper,
|
|
1599
1823
|
{ backgroundColor: colors.background }
|
|
1600
1824
|
]
|
|
1601
1825
|
},
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
resolvedPrefixIcon ? /* @__PURE__ */
|
|
1604
|
-
/* @__PURE__ */
|
|
1826
|
+
/* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles14.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
|
|
1827
|
+
resolvedPrefixIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles14.prefixIcon }, resolvedPrefixIcon) : null,
|
|
1828
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
1605
1829
|
reactNative.TextInput,
|
|
1606
1830
|
{
|
|
1607
1831
|
multiline: true,
|
|
@@ -1630,7 +1854,7 @@ function Textarea({
|
|
|
1630
1854
|
...props
|
|
1631
1855
|
}
|
|
1632
1856
|
)
|
|
1633
|
-
), error ? /* @__PURE__ */
|
|
1857
|
+
), error ? /* @__PURE__ */ React25__default.default.createElement(
|
|
1634
1858
|
reactNative.Text,
|
|
1635
1859
|
{
|
|
1636
1860
|
style: [styles14.helperText, { color: colors.destructive }],
|
|
@@ -1638,7 +1862,7 @@ function Textarea({
|
|
|
1638
1862
|
accessibilityLiveRegion: "polite"
|
|
1639
1863
|
},
|
|
1640
1864
|
error
|
|
1641
|
-
) : null, !error && hint ? /* @__PURE__ */
|
|
1865
|
+
) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles14.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
|
|
1642
1866
|
}
|
|
1643
1867
|
var styles14 = reactNative.StyleSheet.create({
|
|
1644
1868
|
container: {
|
|
@@ -1690,41 +1914,39 @@ function Checkbox({
|
|
|
1690
1914
|
accessibilityLabel
|
|
1691
1915
|
}) {
|
|
1692
1916
|
const { colors } = useTheme();
|
|
1693
|
-
const
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
}
|
|
1697
|
-
const progress = useColorTransition(checked);
|
|
1698
|
-
const boxStyle = Animated9.useAnimatedStyle(() => ({
|
|
1699
|
-
borderColor: Animated9.interpolateColor(progress.value, [0, 1], [colors.border, colors.primary]),
|
|
1700
|
-
backgroundColor: Animated9.interpolateColor(progress.value, [0, 1], ["transparent", colors.primary])
|
|
1701
|
-
}));
|
|
1702
|
-
const checkStyle = Animated9.useAnimatedStyle(() => ({
|
|
1703
|
-
opacity: Animated9.withTiming(checked ? 1 : 0, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
|
|
1704
|
-
}));
|
|
1917
|
+
const handlePress = () => {
|
|
1918
|
+
selectionAsync();
|
|
1919
|
+
onCheckedChange?.(!checked);
|
|
1920
|
+
};
|
|
1705
1921
|
return (
|
|
1706
1922
|
// AUDIT FIX: opacity was applied only to the box, leaving the label at full
|
|
1707
1923
|
// opacity when disabled — a contradictory visual signal. Now the entire row
|
|
1708
1924
|
// dims uniformly so label and control communicate the same disabled state.
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
|
|
1925
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
1926
|
+
PressableButton,
|
|
1711
1927
|
{
|
|
1712
1928
|
style: [styles15.row, disabled && styles15.rowDisabled, style],
|
|
1713
|
-
onPress:
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
},
|
|
1717
|
-
onPressIn,
|
|
1718
|
-
onPressOut,
|
|
1719
|
-
disabled,
|
|
1720
|
-
activeOpacity: 1,
|
|
1929
|
+
onPress: handlePress,
|
|
1930
|
+
enabled: !disabled,
|
|
1931
|
+
rippleColor: "transparent",
|
|
1721
1932
|
touchSoundDisabled: true,
|
|
1722
1933
|
accessibilityRole: "checkbox",
|
|
1723
1934
|
accessibilityLabel: accessibilityLabel ?? label,
|
|
1724
1935
|
accessibilityState: { checked, disabled: !!disabled }
|
|
1725
1936
|
},
|
|
1726
|
-
/* @__PURE__ */
|
|
1727
|
-
|
|
1937
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
1938
|
+
reactNativeEase.EaseView,
|
|
1939
|
+
{
|
|
1940
|
+
style: styles15.box,
|
|
1941
|
+
animate: {
|
|
1942
|
+
borderColor: checked ? colors.primary : colors.border,
|
|
1943
|
+
backgroundColor: checked ? colors.primary : "transparent"
|
|
1944
|
+
},
|
|
1945
|
+
transition: COLOR_TRANSITION
|
|
1946
|
+
},
|
|
1947
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNativeEase.EaseView, { animate: { opacity: checked ? 1 : 0 }, transition: OPACITY_TRANSITION }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles15.checkmark, { borderColor: colors.primaryForeground }] }))
|
|
1948
|
+
),
|
|
1949
|
+
label ? /* @__PURE__ */ React25__default.default.createElement(
|
|
1728
1950
|
reactNative.Text,
|
|
1729
1951
|
{
|
|
1730
1952
|
style: [styles15.label, { color: colors.foreground }],
|
|
@@ -1774,35 +1996,7 @@ var THUMB_TRAVEL = TRACK_WIDTH - THUMB_SIZE - THUMB_OFFSET * 2;
|
|
|
1774
1996
|
var ICON_SIZE = s(13);
|
|
1775
1997
|
function Switch({ checked = false, onCheckedChange, disabled, style, accessibilityLabel }) {
|
|
1776
1998
|
const { colors } = useTheme();
|
|
1777
|
-
|
|
1778
|
-
React26.useEffect(() => {
|
|
1779
|
-
progress.value = Animated9.withSpring(checked ? 1 : 0, SPRINGS.elastic);
|
|
1780
|
-
}, [checked, progress]);
|
|
1781
|
-
const thumbStyle = Animated9.useAnimatedStyle(() => ({
|
|
1782
|
-
transform: [{ translateX: progress.value * THUMB_TRAVEL }]
|
|
1783
|
-
}));
|
|
1784
|
-
const trackStyle = Animated9.useAnimatedStyle(() => ({
|
|
1785
|
-
backgroundColor: Animated9.interpolateColor(
|
|
1786
|
-
progress.value,
|
|
1787
|
-
[0, 1],
|
|
1788
|
-
[colors.surfaceStrong, colors.primary]
|
|
1789
|
-
)
|
|
1790
|
-
}));
|
|
1791
|
-
const trackBorderStyle = Animated9.useAnimatedStyle(() => ({
|
|
1792
|
-
borderWidth: 1.5,
|
|
1793
|
-
borderColor: Animated9.interpolateColor(
|
|
1794
|
-
progress.value,
|
|
1795
|
-
[0, 1],
|
|
1796
|
-
[colors.border, "transparent"]
|
|
1797
|
-
)
|
|
1798
|
-
}));
|
|
1799
|
-
const checkIconStyle = Animated9.useAnimatedStyle(() => ({
|
|
1800
|
-
opacity: Animated9.withTiming(checked ? 1 : 0, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
|
|
1801
|
-
}));
|
|
1802
|
-
const crossIconStyle = Animated9.useAnimatedStyle(() => ({
|
|
1803
|
-
opacity: Animated9.withTiming(checked ? 0 : 1, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
|
|
1804
|
-
}));
|
|
1805
|
-
return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [{ opacity: disabled ? 0.45 : 1, alignSelf: "flex-start" }, style] }, /* @__PURE__ */ React26__default.default.createElement(
|
|
1999
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [{ opacity: disabled ? 0.45 : 1, alignSelf: "flex-start" }, style] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
1806
2000
|
reactNative.TouchableOpacity,
|
|
1807
2001
|
{
|
|
1808
2002
|
onPress: () => {
|
|
@@ -1817,14 +2011,33 @@ function Switch({ checked = false, onCheckedChange, disabled, style, accessibili
|
|
|
1817
2011
|
accessibilityState: { checked, disabled: !!disabled },
|
|
1818
2012
|
style: styles16.touchable
|
|
1819
2013
|
},
|
|
1820
|
-
/* @__PURE__ */
|
|
1821
|
-
|
|
2014
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2015
|
+
reactNativeEase.EaseView,
|
|
1822
2016
|
{
|
|
1823
|
-
style:
|
|
2017
|
+
style: styles16.track,
|
|
2018
|
+
animate: { backgroundColor: checked ? colors.primary : colors.surfaceStrong },
|
|
2019
|
+
transition: COLOR_TRANSITION
|
|
1824
2020
|
},
|
|
1825
|
-
/* @__PURE__ */
|
|
1826
|
-
|
|
1827
|
-
|
|
2021
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2022
|
+
reactNativeEase.EaseView,
|
|
2023
|
+
{
|
|
2024
|
+
style: [styles16.trackBorder, { borderWidth: 1.5 }],
|
|
2025
|
+
pointerEvents: "none",
|
|
2026
|
+
animate: { borderColor: checked ? "transparent" : colors.border },
|
|
2027
|
+
transition: COLOR_TRANSITION
|
|
2028
|
+
}
|
|
2029
|
+
),
|
|
2030
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2031
|
+
reactNativeEase.EaseView,
|
|
2032
|
+
{
|
|
2033
|
+
style: [styles16.thumb, { backgroundColor: colors.primaryForeground }],
|
|
2034
|
+
animate: { translateX: checked ? THUMB_TRAVEL : 0 },
|
|
2035
|
+
transition: SPRING_ELASTIC
|
|
2036
|
+
},
|
|
2037
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNativeEase.EaseView, { style: styles16.iconWrapper, animate: { opacity: checked ? 1 : 0 }, transition: OPACITY_TRANSITION }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "check", size: ICON_SIZE, color: colors.primary })),
|
|
2038
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNativeEase.EaseView, { style: styles16.iconWrapper, animate: { opacity: checked ? 0 : 1 }, transition: OPACITY_TRANSITION }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: ICON_SIZE, color: colors.foregroundMuted }))
|
|
2039
|
+
)
|
|
2040
|
+
)
|
|
1828
2041
|
));
|
|
1829
2042
|
}
|
|
1830
2043
|
var styles16 = reactNative.StyleSheet.create({
|
|
@@ -1868,15 +2081,15 @@ function ToggleIcon({ pressed, iconName, activeIconName, icon, activeIcon, iconC
|
|
|
1868
2081
|
return prop;
|
|
1869
2082
|
};
|
|
1870
2083
|
if (pressed) {
|
|
1871
|
-
if (activeIconName) return /* @__PURE__ */
|
|
2084
|
+
if (activeIconName) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, renderIcon(activeIconName, iconSize, activeIconColor ?? primaryColor));
|
|
1872
2085
|
const active = renderProp(activeIcon);
|
|
1873
|
-
if (active) return /* @__PURE__ */
|
|
1874
|
-
return /* @__PURE__ */
|
|
2086
|
+
if (active) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, active);
|
|
2087
|
+
return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: iconSize, color: primaryColor });
|
|
1875
2088
|
}
|
|
1876
|
-
if (iconName) return /* @__PURE__ */
|
|
2089
|
+
if (iconName) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, renderIcon(iconName, iconSize, iconColor ?? mutedColor));
|
|
1877
2090
|
const custom = renderProp(icon);
|
|
1878
|
-
if (custom) return /* @__PURE__ */
|
|
1879
|
-
return /* @__PURE__ */
|
|
2091
|
+
if (custom) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, custom);
|
|
2092
|
+
return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "circle", size: iconSize, color: mutedColor });
|
|
1880
2093
|
}
|
|
1881
2094
|
var sizeStyles = {
|
|
1882
2095
|
sm: { paddingHorizontal: s(12), paddingVertical: vs(8), minWidth: s(40), minHeight: vs(40) },
|
|
@@ -1898,75 +2111,61 @@ function Toggle({
|
|
|
1898
2111
|
activeIconColor,
|
|
1899
2112
|
disabled,
|
|
1900
2113
|
style,
|
|
1901
|
-
accessibilityLabel
|
|
1902
|
-
...props
|
|
2114
|
+
accessibilityLabel
|
|
1903
2115
|
}) {
|
|
1904
2116
|
const { colors } = useTheme();
|
|
1905
|
-
const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
1906
|
-
pressScale: PRESS_SCALE.button,
|
|
1907
|
-
disabled
|
|
1908
|
-
});
|
|
1909
|
-
const progress = useColorTransition(pressed);
|
|
1910
2117
|
const inactiveBorder = variant === "outline" ? colors.border : "transparent";
|
|
1911
|
-
const surfaceStyle = Animated9.useAnimatedStyle(() => ({
|
|
1912
|
-
borderColor: Animated9.interpolateColor(progress.value, [0, 1], [inactiveBorder, colors.primary]),
|
|
1913
|
-
backgroundColor: Animated9.interpolateColor(progress.value, [0, 1], ["transparent", colors.surfaceStrong])
|
|
1914
|
-
}));
|
|
1915
|
-
const textStyle = Animated9.useAnimatedStyle(() => ({
|
|
1916
|
-
color: Animated9.interpolateColor(progress.value, [0, 1], [colors.foreground, colors.primary])
|
|
1917
|
-
}));
|
|
1918
2118
|
const iconSize = iconSizeMap2[size];
|
|
1919
|
-
|
|
1920
|
-
|
|
2119
|
+
const handlePress = () => {
|
|
2120
|
+
selectionAsync();
|
|
2121
|
+
onPressedChange?.(!pressed);
|
|
2122
|
+
};
|
|
2123
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [disabled && styles17.disabled, style] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2124
|
+
PressableButton,
|
|
1921
2125
|
{
|
|
1922
|
-
|
|
1923
|
-
|
|
2126
|
+
onPress: handlePress,
|
|
2127
|
+
enabled: !disabled,
|
|
2128
|
+
rippleColor: "transparent",
|
|
2129
|
+
touchSoundDisabled: true,
|
|
2130
|
+
activateOnHover: true,
|
|
2131
|
+
accessibilityRole: "button",
|
|
2132
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
2133
|
+
accessibilityState: { selected: pressed, disabled: !!disabled }
|
|
1924
2134
|
},
|
|
1925
|
-
/* @__PURE__ */
|
|
1926
|
-
|
|
2135
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2136
|
+
reactNativeEase.EaseView,
|
|
1927
2137
|
{
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
2138
|
+
style: [styles17.base, sizeStyles[size], { borderWidth: 2 }],
|
|
2139
|
+
animate: {
|
|
2140
|
+
borderColor: pressed ? colors.primary : inactiveBorder,
|
|
2141
|
+
backgroundColor: pressed ? colors.surfaceStrong : "transparent"
|
|
1931
2142
|
},
|
|
1932
|
-
|
|
1933
|
-
onPressOut,
|
|
1934
|
-
disabled,
|
|
1935
|
-
activeOpacity: 1,
|
|
1936
|
-
touchSoundDisabled: true,
|
|
1937
|
-
accessibilityRole: "button",
|
|
1938
|
-
accessibilityLabel: accessibilityLabel ?? label,
|
|
1939
|
-
accessibilityState: { selected: pressed, disabled: !!disabled },
|
|
1940
|
-
...props
|
|
2143
|
+
transition: COLOR_TRANSITION
|
|
1941
2144
|
},
|
|
1942
|
-
/* @__PURE__ */
|
|
1943
|
-
|
|
2145
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles17.inner }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2146
|
+
ToggleIcon,
|
|
2147
|
+
{
|
|
2148
|
+
pressed,
|
|
2149
|
+
iconName,
|
|
2150
|
+
activeIconName,
|
|
2151
|
+
icon,
|
|
2152
|
+
activeIcon,
|
|
2153
|
+
iconColor,
|
|
2154
|
+
activeIconColor,
|
|
2155
|
+
iconSize,
|
|
2156
|
+
primaryColor: colors.primary,
|
|
2157
|
+
mutedColor: colors.foregroundMuted
|
|
2158
|
+
}
|
|
2159
|
+
), label ? /* @__PURE__ */ React25__default.default.createElement(
|
|
2160
|
+
reactNative.Text,
|
|
1944
2161
|
{
|
|
1945
|
-
style: [
|
|
1946
|
-
|
|
1947
|
-
sizeStyles[size],
|
|
1948
|
-
{ borderWidth: 2 },
|
|
1949
|
-
surfaceStyle
|
|
1950
|
-
]
|
|
2162
|
+
style: [styles17.label, { color: pressed ? colors.primary : colors.foreground }],
|
|
2163
|
+
allowFontScaling: true
|
|
1951
2164
|
},
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
{
|
|
1955
|
-
pressed,
|
|
1956
|
-
iconName,
|
|
1957
|
-
activeIconName,
|
|
1958
|
-
icon,
|
|
1959
|
-
activeIcon,
|
|
1960
|
-
iconColor,
|
|
1961
|
-
activeIconColor,
|
|
1962
|
-
iconSize,
|
|
1963
|
-
primaryColor: colors.primary,
|
|
1964
|
-
mutedColor: colors.foregroundMuted
|
|
1965
|
-
}
|
|
1966
|
-
), label ? /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.Text, { style: [styles17.label, textStyle], allowFontScaling: true }, label) : null)
|
|
1967
|
-
)
|
|
2165
|
+
label
|
|
2166
|
+
) : null)
|
|
1968
2167
|
)
|
|
1969
|
-
);
|
|
2168
|
+
));
|
|
1970
2169
|
}
|
|
1971
2170
|
var styles17 = reactNative.StyleSheet.create({
|
|
1972
2171
|
base: {
|
|
@@ -1986,6 +2185,49 @@ var styles17 = reactNative.StyleSheet.create({
|
|
|
1986
2185
|
fontSize: ms(14)
|
|
1987
2186
|
}
|
|
1988
2187
|
});
|
|
2188
|
+
function useHover() {
|
|
2189
|
+
const [hovered, setHovered] = React25.useState(false);
|
|
2190
|
+
const onMouseEnter = React25.useCallback(() => setHovered(true), []);
|
|
2191
|
+
const onMouseLeave = React25.useCallback(() => setHovered(false), []);
|
|
2192
|
+
if (reactNative.Platform.OS !== "web") {
|
|
2193
|
+
return { hovered: false, hoverHandlers: {} };
|
|
2194
|
+
}
|
|
2195
|
+
return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
// src/utils/usePressScale.ts
|
|
2199
|
+
function usePressScale({
|
|
2200
|
+
pressScale = PRESS_SCALE.button,
|
|
2201
|
+
hoverScale = 1.02,
|
|
2202
|
+
pressInSpring = SPRINGS.pressIn,
|
|
2203
|
+
pressOutSpring = SPRINGS.pressOut,
|
|
2204
|
+
disabled = false
|
|
2205
|
+
} = {}) {
|
|
2206
|
+
const scale2 = Animated13.useSharedValue(1);
|
|
2207
|
+
const { hovered, hoverHandlers } = useHover();
|
|
2208
|
+
const onPressIn = React25.useCallback(() => {
|
|
2209
|
+
if (disabled) return;
|
|
2210
|
+
scale2.value = Animated13.withSpring(pressScale, pressInSpring);
|
|
2211
|
+
}, [disabled, pressScale, pressInSpring, scale2]);
|
|
2212
|
+
const onPressOut = React25.useCallback(() => {
|
|
2213
|
+
if (disabled) return;
|
|
2214
|
+
scale2.value = Animated13.withSpring(1, pressOutSpring);
|
|
2215
|
+
}, [disabled, pressOutSpring, scale2]);
|
|
2216
|
+
const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
|
|
2217
|
+
const animatedStyle = Animated13.useAnimatedStyle(() => ({
|
|
2218
|
+
transform: [
|
|
2219
|
+
{ scale: scale2.value * (hoverActive ? hoverScale : 1) }
|
|
2220
|
+
]
|
|
2221
|
+
}));
|
|
2222
|
+
return {
|
|
2223
|
+
animatedStyle,
|
|
2224
|
+
onPressIn,
|
|
2225
|
+
onPressOut,
|
|
2226
|
+
hoverHandlers
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
// src/components/RadioGroup/RadioGroup.tsx
|
|
1989
2231
|
function RadioItem({
|
|
1990
2232
|
option,
|
|
1991
2233
|
selected,
|
|
@@ -1996,23 +2238,11 @@ function RadioItem({
|
|
|
1996
2238
|
pressScale: PRESS_SCALE.button,
|
|
1997
2239
|
disabled: option.disabled
|
|
1998
2240
|
});
|
|
1999
|
-
const colorProgress = useColorTransition(selected);
|
|
2000
|
-
const dotScale = Animated9.useSharedValue(selected ? 1 : 0);
|
|
2001
|
-
React26.useEffect(() => {
|
|
2002
|
-
dotScale.value = Animated9.withSpring(selected ? 1 : 0, SPRINGS.elastic);
|
|
2003
|
-
}, [selected, dotScale]);
|
|
2004
|
-
const radioStyle = Animated9.useAnimatedStyle(() => ({
|
|
2005
|
-
borderColor: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.border, colors.primary])
|
|
2006
|
-
}));
|
|
2007
|
-
const dotStyle = Animated9.useAnimatedStyle(() => ({
|
|
2008
|
-
transform: [{ scale: dotScale.value }],
|
|
2009
|
-
opacity: dotScale.value
|
|
2010
|
-
}));
|
|
2011
2241
|
return (
|
|
2012
2242
|
// AUDIT FIX: opacity was applied only to the radio circle, leaving the label
|
|
2013
2243
|
// at full opacity when disabled. The whole row now dims uniformly so users
|
|
2014
2244
|
// get a single, consistent disabled signal across the entire item.
|
|
2015
|
-
/* @__PURE__ */
|
|
2245
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2016
2246
|
reactNative.TouchableOpacity,
|
|
2017
2247
|
{
|
|
2018
2248
|
style: [styles18.row, option.disabled && styles18.rowDisabled],
|
|
@@ -2031,8 +2261,23 @@ function RadioItem({
|
|
|
2031
2261
|
accessibilityLabel: option.label,
|
|
2032
2262
|
accessibilityState: { checked: selected, disabled: !!option.disabled }
|
|
2033
2263
|
},
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
|
|
2264
|
+
/* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: scaleStyle }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2265
|
+
reactNativeEase.EaseView,
|
|
2266
|
+
{
|
|
2267
|
+
style: styles18.radio,
|
|
2268
|
+
animate: { borderColor: selected ? colors.primary : colors.border },
|
|
2269
|
+
transition: COLOR_TRANSITION
|
|
2270
|
+
},
|
|
2271
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2272
|
+
reactNativeEase.EaseView,
|
|
2273
|
+
{
|
|
2274
|
+
style: [styles18.dot, { backgroundColor: colors.primary }],
|
|
2275
|
+
animate: { scale: selected ? 1 : 0, opacity: selected ? 1 : 0 },
|
|
2276
|
+
transition: SPRING_ELASTIC
|
|
2277
|
+
}
|
|
2278
|
+
)
|
|
2279
|
+
)),
|
|
2280
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2036
2281
|
reactNative.Text,
|
|
2037
2282
|
{
|
|
2038
2283
|
style: [styles18.label, { color: colors.foreground }],
|
|
@@ -2051,14 +2296,14 @@ function RadioGroup({
|
|
|
2051
2296
|
style,
|
|
2052
2297
|
accessibilityLabel
|
|
2053
2298
|
}) {
|
|
2054
|
-
return /* @__PURE__ */
|
|
2299
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
2055
2300
|
reactNative.View,
|
|
2056
2301
|
{
|
|
2057
2302
|
style: [styles18.container, orientation === "horizontal" && styles18.horizontal, style],
|
|
2058
2303
|
accessibilityRole: "radiogroup",
|
|
2059
2304
|
accessibilityLabel
|
|
2060
2305
|
},
|
|
2061
|
-
options.map((option) => /* @__PURE__ */
|
|
2306
|
+
options.map((option) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2062
2307
|
RadioItem,
|
|
2063
2308
|
{
|
|
2064
2309
|
key: option.value,
|
|
@@ -2113,12 +2358,9 @@ function TabTrigger({
|
|
|
2113
2358
|
variant
|
|
2114
2359
|
}) {
|
|
2115
2360
|
const { colors } = useTheme();
|
|
2116
|
-
const { animatedStyle, onPressIn, onPressOut } = usePressScale({
|
|
2117
|
-
pressScale: PRESS_SCALE.button
|
|
2118
|
-
});
|
|
2119
2361
|
const isUnderline = variant === "underline";
|
|
2120
|
-
return /* @__PURE__ */
|
|
2121
|
-
|
|
2362
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { onLayout, style: styles19.triggerWrap }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2363
|
+
PressableTab,
|
|
2122
2364
|
{
|
|
2123
2365
|
style: [
|
|
2124
2366
|
styles19.trigger,
|
|
@@ -2126,16 +2368,13 @@ function TabTrigger({
|
|
|
2126
2368
|
isUnderline && isActive && { borderBottomColor: colors.primary }
|
|
2127
2369
|
],
|
|
2128
2370
|
onPress,
|
|
2129
|
-
|
|
2130
|
-
onPressOut,
|
|
2131
|
-
onLayout,
|
|
2132
|
-
activeOpacity: 1,
|
|
2371
|
+
rippleColor: "transparent",
|
|
2133
2372
|
touchSoundDisabled: true,
|
|
2134
2373
|
accessibilityRole: "tab",
|
|
2135
2374
|
accessibilityState: { selected: isActive },
|
|
2136
2375
|
accessibilityLabel: tab.label
|
|
2137
2376
|
},
|
|
2138
|
-
/* @__PURE__ */
|
|
2377
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles19.triggerInner }, tab.icon ? typeof tab.icon === "function" ? tab.icon(isActive) : tab.icon : null, /* @__PURE__ */ React25__default.default.createElement(
|
|
2139
2378
|
reactNative.Text,
|
|
2140
2379
|
{
|
|
2141
2380
|
style: [
|
|
@@ -2149,29 +2388,29 @@ function TabTrigger({
|
|
|
2149
2388
|
allowFontScaling: true
|
|
2150
2389
|
},
|
|
2151
2390
|
tab.label
|
|
2152
|
-
))
|
|
2153
|
-
);
|
|
2391
|
+
))
|
|
2392
|
+
));
|
|
2154
2393
|
}
|
|
2155
2394
|
function Tabs({ tabs, variant = "pill", value, onValueChange, children, style }) {
|
|
2156
|
-
const [internal, setInternal] =
|
|
2395
|
+
const [internal, setInternal] = React25.useState(tabs[0]?.value ?? "");
|
|
2157
2396
|
const { colors } = useTheme();
|
|
2158
2397
|
const active = value ?? internal;
|
|
2159
|
-
const tabLayouts =
|
|
2160
|
-
const pillX =
|
|
2161
|
-
const pillWidth =
|
|
2162
|
-
const initialised =
|
|
2163
|
-
const animatePill =
|
|
2398
|
+
const tabLayouts = React25.useRef({});
|
|
2399
|
+
const pillX = Animated13.useSharedValue(0);
|
|
2400
|
+
const pillWidth = Animated13.useSharedValue(0);
|
|
2401
|
+
const initialised = React25.useRef(false);
|
|
2402
|
+
const animatePill = React25.useCallback((tabValue, animate) => {
|
|
2164
2403
|
const layout = tabLayouts.current[tabValue];
|
|
2165
2404
|
if (!layout) return;
|
|
2166
2405
|
if (animate) {
|
|
2167
|
-
pillX.value =
|
|
2168
|
-
pillWidth.value =
|
|
2406
|
+
pillX.value = Animated13.withSpring(layout.x, SPRINGS.glide);
|
|
2407
|
+
pillWidth.value = Animated13.withSpring(layout.width, SPRINGS.glide);
|
|
2169
2408
|
} else {
|
|
2170
2409
|
pillX.value = layout.x;
|
|
2171
2410
|
pillWidth.value = layout.width;
|
|
2172
2411
|
}
|
|
2173
2412
|
}, [pillX, pillWidth]);
|
|
2174
|
-
|
|
2413
|
+
React25.useEffect(() => {
|
|
2175
2414
|
if (initialised.current) animatePill(active, true);
|
|
2176
2415
|
}, [active, animatePill]);
|
|
2177
2416
|
const handlePress = (v) => {
|
|
@@ -2179,11 +2418,11 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
|
|
|
2179
2418
|
if (!value) setInternal(v);
|
|
2180
2419
|
onValueChange?.(v);
|
|
2181
2420
|
};
|
|
2182
|
-
const pillAnimatedStyle =
|
|
2421
|
+
const pillAnimatedStyle = Animated13.useAnimatedStyle(() => ({
|
|
2183
2422
|
transform: [{ translateX: pillX.value }],
|
|
2184
2423
|
width: pillWidth.value
|
|
2185
2424
|
}));
|
|
2186
|
-
return /* @__PURE__ */
|
|
2425
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2187
2426
|
reactNative.View,
|
|
2188
2427
|
{
|
|
2189
2428
|
style: [
|
|
@@ -2191,8 +2430,8 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
|
|
|
2191
2430
|
],
|
|
2192
2431
|
accessibilityRole: "tablist"
|
|
2193
2432
|
},
|
|
2194
|
-
variant === "pill" && /* @__PURE__ */
|
|
2195
|
-
|
|
2433
|
+
variant === "pill" && /* @__PURE__ */ React25__default.default.createElement(
|
|
2434
|
+
Animated13__default.default.View,
|
|
2196
2435
|
{
|
|
2197
2436
|
style: [
|
|
2198
2437
|
styles19.pill,
|
|
@@ -2213,7 +2452,7 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
|
|
|
2213
2452
|
]
|
|
2214
2453
|
}
|
|
2215
2454
|
),
|
|
2216
|
-
tabs.map((tab) => /* @__PURE__ */
|
|
2455
|
+
tabs.map((tab) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2217
2456
|
TabTrigger,
|
|
2218
2457
|
{
|
|
2219
2458
|
key: tab.value,
|
|
@@ -2235,7 +2474,7 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
|
|
|
2235
2474
|
}
|
|
2236
2475
|
function TabsContent({ value, activeValue, children, style }) {
|
|
2237
2476
|
if (value !== activeValue) return null;
|
|
2238
|
-
return /* @__PURE__ */
|
|
2477
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style, accessibilityRole: "none" }, children);
|
|
2239
2478
|
}
|
|
2240
2479
|
var styles19 = reactNative.StyleSheet.create({
|
|
2241
2480
|
list: {
|
|
@@ -2251,6 +2490,9 @@ var styles19 = reactNative.StyleSheet.create({
|
|
|
2251
2490
|
borderBottomWidth: 1
|
|
2252
2491
|
},
|
|
2253
2492
|
pill: {},
|
|
2493
|
+
triggerWrap: {
|
|
2494
|
+
flex: 1
|
|
2495
|
+
},
|
|
2254
2496
|
trigger: {
|
|
2255
2497
|
flex: 1,
|
|
2256
2498
|
paddingVertical: vs(7),
|
|
@@ -2261,7 +2503,7 @@ var styles19 = reactNative.StyleSheet.create({
|
|
|
2261
2503
|
zIndex: 1
|
|
2262
2504
|
},
|
|
2263
2505
|
triggerUnderline: {
|
|
2264
|
-
flex:
|
|
2506
|
+
flex: 1,
|
|
2265
2507
|
paddingVertical: vs(12),
|
|
2266
2508
|
paddingHorizontal: s(16),
|
|
2267
2509
|
borderRadius: 0,
|
|
@@ -2291,31 +2533,31 @@ function AccordionItemComponent({
|
|
|
2291
2533
|
}) {
|
|
2292
2534
|
const { colors } = useTheme();
|
|
2293
2535
|
const resolvedIcon = item.iconName ? renderIcon(item.iconName, ms(16), item.iconColor ?? colors.foregroundMuted) : item.icon;
|
|
2294
|
-
const isExpanded =
|
|
2295
|
-
const height =
|
|
2296
|
-
|
|
2536
|
+
const isExpanded = Animated13.useSharedValue(isOpen);
|
|
2537
|
+
const height = Animated13.useSharedValue(0);
|
|
2538
|
+
React25__default.default.useEffect(() => {
|
|
2297
2539
|
isExpanded.value = isOpen;
|
|
2298
2540
|
}, [isOpen, isExpanded]);
|
|
2299
|
-
const derivedHeight =
|
|
2300
|
-
() =>
|
|
2541
|
+
const derivedHeight = Animated13.useDerivedValue(
|
|
2542
|
+
() => Animated13.withTiming(height.value * Number(isExpanded.value), {
|
|
2301
2543
|
duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
|
|
2302
2544
|
easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
|
|
2303
2545
|
})
|
|
2304
2546
|
);
|
|
2305
|
-
const derivedRotation =
|
|
2306
|
-
() =>
|
|
2547
|
+
const derivedRotation = Animated13.useDerivedValue(
|
|
2548
|
+
() => Animated13.withTiming(isExpanded.value ? 1 : 0, {
|
|
2307
2549
|
duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
|
|
2308
2550
|
easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
|
|
2309
2551
|
})
|
|
2310
2552
|
);
|
|
2311
|
-
const bodyStyle =
|
|
2553
|
+
const bodyStyle = Animated13.useAnimatedStyle(() => ({
|
|
2312
2554
|
height: derivedHeight.value,
|
|
2313
2555
|
overflow: "hidden"
|
|
2314
2556
|
}));
|
|
2315
|
-
const rotationStyle =
|
|
2557
|
+
const rotationStyle = Animated13.useAnimatedStyle(() => ({
|
|
2316
2558
|
transform: [{ rotate: `${derivedRotation.value * 180}deg` }]
|
|
2317
2559
|
}));
|
|
2318
|
-
return /* @__PURE__ */
|
|
2560
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles20.item, { backgroundColor: colors.card, borderColor: colors.border }] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2319
2561
|
reactNative.Pressable,
|
|
2320
2562
|
{
|
|
2321
2563
|
style: ({ pressed }) => [styles20.trigger, { opacity: pressed ? 0.6 : 1 }],
|
|
@@ -2327,9 +2569,9 @@ function AccordionItemComponent({
|
|
|
2327
2569
|
accessibilityState: { expanded: isOpen },
|
|
2328
2570
|
accessibilityLabel: item.trigger
|
|
2329
2571
|
},
|
|
2330
|
-
/* @__PURE__ */
|
|
2331
|
-
/* @__PURE__ */
|
|
2332
|
-
), /* @__PURE__ */
|
|
2572
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles20.triggerContent }, resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles20.icon }, resolvedIcon) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger)),
|
|
2573
|
+
/* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles20.chevron, rotationStyle] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
|
|
2574
|
+
), /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2333
2575
|
reactNative.View,
|
|
2334
2576
|
{
|
|
2335
2577
|
style: styles20.content,
|
|
@@ -2337,11 +2579,11 @@ function AccordionItemComponent({
|
|
|
2337
2579
|
height.value = e.nativeEvent.layout.height;
|
|
2338
2580
|
}
|
|
2339
2581
|
},
|
|
2340
|
-
item.content
|
|
2582
|
+
typeof item.content === "string" || typeof item.content === "number" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.contentText, { color: colors.foregroundMuted }], allowFontScaling: true }, item.content) : item.content
|
|
2341
2583
|
)));
|
|
2342
2584
|
}
|
|
2343
2585
|
function Accordion({ items, type = "single", defaultValue, style }) {
|
|
2344
|
-
const [openValues, setOpenValues] =
|
|
2586
|
+
const [openValues, setOpenValues] = React25.useState(() => {
|
|
2345
2587
|
if (!defaultValue) return [];
|
|
2346
2588
|
return Array.isArray(defaultValue) ? defaultValue : [defaultValue];
|
|
2347
2589
|
});
|
|
@@ -2354,7 +2596,7 @@ function Accordion({ items, type = "single", defaultValue, style }) {
|
|
|
2354
2596
|
);
|
|
2355
2597
|
}
|
|
2356
2598
|
};
|
|
2357
|
-
return /* @__PURE__ */
|
|
2599
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles20.list, style] }, items.map((item) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2358
2600
|
AccordionItemComponent,
|
|
2359
2601
|
{
|
|
2360
2602
|
key: item.value,
|
|
@@ -2404,6 +2646,11 @@ var styles20 = reactNative.StyleSheet.create({
|
|
|
2404
2646
|
paddingBottom: vs(12),
|
|
2405
2647
|
position: "absolute",
|
|
2406
2648
|
width: "100%"
|
|
2649
|
+
},
|
|
2650
|
+
contentText: {
|
|
2651
|
+
fontFamily: "Sohne-Regular",
|
|
2652
|
+
fontSize: ms(14),
|
|
2653
|
+
lineHeight: ms(20)
|
|
2407
2654
|
}
|
|
2408
2655
|
});
|
|
2409
2656
|
function Slider({
|
|
@@ -2421,7 +2668,7 @@ function Slider({
|
|
|
2421
2668
|
style
|
|
2422
2669
|
}) {
|
|
2423
2670
|
const { colors } = useTheme();
|
|
2424
|
-
const lastSteppedValue =
|
|
2671
|
+
const lastSteppedValue = React25.useRef(value);
|
|
2425
2672
|
const handleValueChange = (v) => {
|
|
2426
2673
|
if (step && v !== lastSteppedValue.current) {
|
|
2427
2674
|
lastSteppedValue.current = v;
|
|
@@ -2429,7 +2676,7 @@ function Slider({
|
|
|
2429
2676
|
}
|
|
2430
2677
|
onValueChange?.(v);
|
|
2431
2678
|
};
|
|
2432
|
-
return /* @__PURE__ */
|
|
2679
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
2433
2680
|
reactNative.View,
|
|
2434
2681
|
{
|
|
2435
2682
|
style: [styles21.wrapper, style],
|
|
@@ -2442,8 +2689,8 @@ function Slider({
|
|
|
2442
2689
|
text: formatValue2(value)
|
|
2443
2690
|
}
|
|
2444
2691
|
},
|
|
2445
|
-
label || showValue ? /* @__PURE__ */
|
|
2446
|
-
/* @__PURE__ */
|
|
2692
|
+
label || showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles21.header }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.valueText, { color: colors.foregroundMuted }], allowFontScaling: true }, formatValue2(value)) : null) : null,
|
|
2693
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled ? styles21.disabled : void 0 }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2447
2694
|
RNSlider__default.default,
|
|
2448
2695
|
{
|
|
2449
2696
|
value,
|
|
@@ -2491,14 +2738,14 @@ var SCREEN_HEIGHT = reactNative.Dimensions.get("window").height;
|
|
|
2491
2738
|
var DEFAULT_MAX_HEIGHT = SCREEN_HEIGHT * 0.85;
|
|
2492
2739
|
var isAndroid = reactNative.Platform.OS === "android";
|
|
2493
2740
|
function SheetHeader({ children, style }) {
|
|
2494
|
-
return /* @__PURE__ */
|
|
2741
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles22.header, style] }, children);
|
|
2495
2742
|
}
|
|
2496
2743
|
function SheetContent({ children, style }) {
|
|
2497
|
-
return /* @__PURE__ */
|
|
2744
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles22.sheetContent, style] }, children);
|
|
2498
2745
|
}
|
|
2499
2746
|
function SheetFooter({ children, style }) {
|
|
2500
2747
|
const { colors } = useTheme();
|
|
2501
|
-
return /* @__PURE__ */
|
|
2748
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles22.sheetFooter, { backgroundColor: colors.card, borderTopColor: colors.border }, style] }, children);
|
|
2502
2749
|
}
|
|
2503
2750
|
function Sheet({
|
|
2504
2751
|
open,
|
|
@@ -2517,13 +2764,17 @@ function Sheet({
|
|
|
2517
2764
|
enableBlurKeyboardOnGesture = true,
|
|
2518
2765
|
android_keyboardInputMode = "adjustPan",
|
|
2519
2766
|
footer,
|
|
2520
|
-
snapPoints
|
|
2767
|
+
snapPoints,
|
|
2768
|
+
responsive = false,
|
|
2769
|
+
dialogMaxWidth = 480
|
|
2521
2770
|
}) {
|
|
2522
2771
|
const { colors } = useTheme();
|
|
2523
2772
|
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
2524
|
-
const
|
|
2773
|
+
const { width: windowWidth } = reactNative.useWindowDimensions();
|
|
2774
|
+
const ref = React25.useRef(null);
|
|
2775
|
+
const asDialog = responsive && windowWidth >= BREAKPOINTS.wide;
|
|
2525
2776
|
const effectiveKeyboardBehavior = keyboardBehavior ?? "interactive";
|
|
2526
|
-
|
|
2777
|
+
React25.useEffect(() => {
|
|
2527
2778
|
if (open) {
|
|
2528
2779
|
impactMedium();
|
|
2529
2780
|
ref.current?.present();
|
|
@@ -2531,7 +2782,7 @@ function Sheet({
|
|
|
2531
2782
|
ref.current?.dismiss();
|
|
2532
2783
|
}
|
|
2533
2784
|
}, [open]);
|
|
2534
|
-
const renderBackdrop =
|
|
2785
|
+
const renderBackdrop = React25.useCallback((props) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2535
2786
|
bottomSheet.BottomSheetBackdrop,
|
|
2536
2787
|
{
|
|
2537
2788
|
...props,
|
|
@@ -2540,16 +2791,16 @@ function Sheet({
|
|
|
2540
2791
|
pressBehavior: "close"
|
|
2541
2792
|
}
|
|
2542
2793
|
), []);
|
|
2543
|
-
const childArray =
|
|
2544
|
-
const customHeader = childArray.find((child) =>
|
|
2545
|
-
const customContent = childArray.find((child) =>
|
|
2546
|
-
const customFooter = childArray.find((child) =>
|
|
2794
|
+
const childArray = React25__default.default.Children.toArray(children);
|
|
2795
|
+
const customHeader = childArray.find((child) => React25__default.default.isValidElement(child) && child.type === SheetHeader);
|
|
2796
|
+
const customContent = childArray.find((child) => React25__default.default.isValidElement(child) && child.type === SheetContent);
|
|
2797
|
+
const customFooter = childArray.find((child) => React25__default.default.isValidElement(child) && child.type === SheetFooter);
|
|
2547
2798
|
const filteredChildren = customHeader || customContent || customFooter ? childArray.filter(
|
|
2548
|
-
(child) => !
|
|
2799
|
+
(child) => !React25__default.default.isValidElement(child) || child.type !== SheetHeader && child.type !== SheetContent && child.type !== SheetFooter
|
|
2549
2800
|
) : children;
|
|
2550
2801
|
const effectiveSubtitle = subtitle ?? description;
|
|
2551
2802
|
const showHeader = !!(title || effectiveSubtitle || showCloseButton) && !customHeader;
|
|
2552
|
-
const headerNode = customHeader ? customHeader : showHeader ? /* @__PURE__ */
|
|
2803
|
+
const headerNode = customHeader ? customHeader : showHeader ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles22.header, accessibilityRole: "header" }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles22.headerRow }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles22.title, { color: colors.foreground }], allowFontScaling: true }, title) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { flex: 1 } }), showCloseButton ? /* @__PURE__ */ React25__default.default.createElement(
|
|
2553
2804
|
reactNative.TouchableOpacity,
|
|
2554
2805
|
{
|
|
2555
2806
|
onPress: onClose,
|
|
@@ -2560,18 +2811,43 @@ function Sheet({
|
|
|
2560
2811
|
accessibilityLabel: "Close",
|
|
2561
2812
|
hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
|
|
2562
2813
|
},
|
|
2563
|
-
/* @__PURE__ */
|
|
2564
|
-
) : null), effectiveSubtitle ? /* @__PURE__ */
|
|
2814
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: "close", size: ms(18), color: colors.foregroundMuted })
|
|
2815
|
+
) : null), effectiveSubtitle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles22.subtitle, { color: colors.foregroundMuted }], allowFontScaling: true }, effectiveSubtitle) : null) : null;
|
|
2565
2816
|
const contentNode = customContent ? customContent : filteredChildren;
|
|
2566
2817
|
const effectiveFooter = customFooter ? customFooter : footer;
|
|
2567
|
-
const renderFooter =
|
|
2818
|
+
const renderFooter = React25.useCallback((props) => {
|
|
2568
2819
|
if (!effectiveFooter) return null;
|
|
2569
|
-
return /* @__PURE__ */
|
|
2820
|
+
return /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetFooter, { ...props }, effectiveFooter);
|
|
2570
2821
|
}, [effectiveFooter]);
|
|
2822
|
+
if (asDialog) {
|
|
2823
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: onClose }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Pressable, { style: styles22.dialogBackdrop, onPress: onClose, accessibilityRole: "button", accessibilityLabel: "Close" }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2824
|
+
reactNative.Pressable,
|
|
2825
|
+
{
|
|
2826
|
+
style: [
|
|
2827
|
+
styles22.dialogCard,
|
|
2828
|
+
{ backgroundColor: colors.card, maxWidth: dialogMaxWidth, maxHeight: SCREEN_HEIGHT * 0.85 }
|
|
2829
|
+
],
|
|
2830
|
+
onPress: () => {
|
|
2831
|
+
}
|
|
2832
|
+
},
|
|
2833
|
+
headerNode,
|
|
2834
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2835
|
+
reactNative.ScrollView,
|
|
2836
|
+
{
|
|
2837
|
+
contentContainerStyle: [styles22.dialogContent, style],
|
|
2838
|
+
style: contentStyle,
|
|
2839
|
+
showsVerticalScrollIndicator: true,
|
|
2840
|
+
bounces: false
|
|
2841
|
+
},
|
|
2842
|
+
contentNode
|
|
2843
|
+
),
|
|
2844
|
+
effectiveFooter
|
|
2845
|
+
)));
|
|
2846
|
+
}
|
|
2571
2847
|
const useScroll = scrollable || !!maxHeight;
|
|
2572
2848
|
const effectiveMaxHeight = maxHeight ?? DEFAULT_MAX_HEIGHT;
|
|
2573
2849
|
const useDynamicSizing = !snapPoints;
|
|
2574
|
-
return /* @__PURE__ */
|
|
2850
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
2575
2851
|
bottomSheet.BottomSheetModal,
|
|
2576
2852
|
{
|
|
2577
2853
|
ref,
|
|
@@ -2590,7 +2866,7 @@ function Sheet({
|
|
|
2590
2866
|
android_keyboardInputMode,
|
|
2591
2867
|
enableBlurKeyboardOnGesture
|
|
2592
2868
|
},
|
|
2593
|
-
useScroll ? /* @__PURE__ */
|
|
2869
|
+
useScroll ? /* @__PURE__ */ React25__default.default.createElement(
|
|
2594
2870
|
bottomSheet.BottomSheetScrollView,
|
|
2595
2871
|
{
|
|
2596
2872
|
contentContainerStyle: [
|
|
@@ -2604,7 +2880,7 @@ function Sheet({
|
|
|
2604
2880
|
},
|
|
2605
2881
|
headerNode,
|
|
2606
2882
|
contentNode
|
|
2607
|
-
) : /* @__PURE__ */
|
|
2883
|
+
) : /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: [styles22.content, contentStyle, style] }, headerNode, contentNode)
|
|
2608
2884
|
);
|
|
2609
2885
|
}
|
|
2610
2886
|
Sheet.Header = SheetHeader;
|
|
@@ -2663,6 +2939,24 @@ var styles22 = reactNative.StyleSheet.create({
|
|
|
2663
2939
|
borderTopWidth: 1,
|
|
2664
2940
|
flexDirection: "row",
|
|
2665
2941
|
gap: s(12)
|
|
2942
|
+
},
|
|
2943
|
+
dialogBackdrop: {
|
|
2944
|
+
flex: 1,
|
|
2945
|
+
backgroundColor: "rgba(0,0,0,0.5)",
|
|
2946
|
+
alignItems: "center",
|
|
2947
|
+
justifyContent: "center",
|
|
2948
|
+
padding: s(24)
|
|
2949
|
+
},
|
|
2950
|
+
dialogCard: {
|
|
2951
|
+
width: "100%",
|
|
2952
|
+
borderRadius: RADIUS.lg,
|
|
2953
|
+
paddingTop: vs(16),
|
|
2954
|
+
overflow: "hidden",
|
|
2955
|
+
...SHADOWS.xl
|
|
2956
|
+
},
|
|
2957
|
+
dialogContent: {
|
|
2958
|
+
paddingHorizontal: s(16),
|
|
2959
|
+
paddingBottom: vs(16)
|
|
2666
2960
|
}
|
|
2667
2961
|
});
|
|
2668
2962
|
var isIOS = reactNative.Platform.OS === "ios";
|
|
@@ -2684,9 +2978,9 @@ function Select({
|
|
|
2684
2978
|
pressScale: PRESS_SCALE.button,
|
|
2685
2979
|
disabled
|
|
2686
2980
|
});
|
|
2687
|
-
const [pickerVisible, setPickerVisible] =
|
|
2688
|
-
const [pendingValue, setPendingValue] =
|
|
2689
|
-
const pickerRef =
|
|
2981
|
+
const [pickerVisible, setPickerVisible] = React25.useState(false);
|
|
2982
|
+
const [pendingValue, setPendingValue] = React25.useState(value);
|
|
2983
|
+
const pickerRef = React25.useRef(null);
|
|
2690
2984
|
const selected = options.find((o) => o.value === value);
|
|
2691
2985
|
const handleOpen = () => {
|
|
2692
2986
|
if (disabled) return;
|
|
@@ -2708,7 +3002,7 @@ function Select({
|
|
|
2708
3002
|
}
|
|
2709
3003
|
setPickerVisible(false);
|
|
2710
3004
|
};
|
|
2711
|
-
return /* @__PURE__ */
|
|
3005
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [animatedStyle, { opacity: disabled ? 0.45 : 1 }] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
2712
3006
|
reactNative.TouchableOpacity,
|
|
2713
3007
|
{
|
|
2714
3008
|
style: [
|
|
@@ -2728,7 +3022,7 @@ function Select({
|
|
|
2728
3022
|
accessibilityValue: { text: selected?.label ?? placeholder },
|
|
2729
3023
|
accessibilityState: { disabled: !!disabled, expanded: pickerVisible }
|
|
2730
3024
|
},
|
|
2731
|
-
/* @__PURE__ */
|
|
3025
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
2732
3026
|
reactNative.Text,
|
|
2733
3027
|
{
|
|
2734
3028
|
style: [
|
|
@@ -2740,8 +3034,8 @@ function Select({
|
|
|
2740
3034
|
},
|
|
2741
3035
|
selected?.label ?? placeholder
|
|
2742
3036
|
),
|
|
2743
|
-
/* @__PURE__ */
|
|
2744
|
-
)) : null, isIOS ? /* @__PURE__ */
|
|
3037
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 20, color: colors.foregroundMuted })
|
|
3038
|
+
)) : null, isIOS ? /* @__PURE__ */ React25__default.default.createElement(
|
|
2745
3039
|
reactNative.Modal,
|
|
2746
3040
|
{
|
|
2747
3041
|
visible: pickerVisible,
|
|
@@ -2749,16 +3043,16 @@ function Select({
|
|
|
2749
3043
|
animationType: "slide",
|
|
2750
3044
|
onRequestClose: handleDismiss
|
|
2751
3045
|
},
|
|
2752
|
-
/* @__PURE__ */
|
|
2753
|
-
/* @__PURE__ */
|
|
3046
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { style: styles23.iosBackdrop, activeOpacity: 1, onPress: handleDismiss }),
|
|
3047
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles23.iosSheet, { backgroundColor: colors.card }] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles23.iosToolbar, { borderBottomColor: colors.border }] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.iosToolbarTitle, { color: colors.foreground }], allowFontScaling: true }, label) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, null), /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { onPress: handleConfirm, style: styles23.iosDoneBtn, hitSlop: { top: 8, bottom: 8, left: 8, right: 8 } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.iosDoneBtnText, { color: colors.primary }], allowFontScaling: true }, "Done"))), /* @__PURE__ */ React25__default.default.createElement(
|
|
2754
3048
|
picker.Picker,
|
|
2755
3049
|
{
|
|
2756
3050
|
selectedValue: pendingValue ?? "",
|
|
2757
3051
|
onValueChange: (val) => setPendingValue(val),
|
|
2758
3052
|
itemStyle: { color: colors.foreground }
|
|
2759
3053
|
},
|
|
2760
|
-
!value ? /* @__PURE__ */
|
|
2761
|
-
options.map((o) => /* @__PURE__ */
|
|
3054
|
+
!value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.foregroundMuted, enabled: false }) : null,
|
|
3055
|
+
options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2762
3056
|
picker.Picker.Item,
|
|
2763
3057
|
{
|
|
2764
3058
|
key: o.value,
|
|
@@ -2769,7 +3063,7 @@ function Select({
|
|
|
2769
3063
|
}
|
|
2770
3064
|
))
|
|
2771
3065
|
))
|
|
2772
|
-
) : null, isAndroid2 ? /* @__PURE__ */
|
|
3066
|
+
) : null, isAndroid2 ? /* @__PURE__ */ React25__default.default.createElement(
|
|
2773
3067
|
picker.Picker,
|
|
2774
3068
|
{
|
|
2775
3069
|
ref: pickerRef,
|
|
@@ -2785,8 +3079,8 @@ function Select({
|
|
|
2785
3079
|
prompt: label,
|
|
2786
3080
|
style: styles23.androidHiddenPicker
|
|
2787
3081
|
},
|
|
2788
|
-
!value ? /* @__PURE__ */
|
|
2789
|
-
options.map((o) => /* @__PURE__ */
|
|
3082
|
+
!value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", enabled: false }) : null,
|
|
3083
|
+
options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2790
3084
|
picker.Picker.Item,
|
|
2791
3085
|
{
|
|
2792
3086
|
key: o.value,
|
|
@@ -2795,7 +3089,7 @@ function Select({
|
|
|
2795
3089
|
enabled: !o.disabled
|
|
2796
3090
|
}
|
|
2797
3091
|
))
|
|
2798
|
-
) : null, isWeb2 ? /* @__PURE__ */
|
|
3092
|
+
) : null, isWeb2 ? /* @__PURE__ */ React25__default.default.createElement(
|
|
2799
3093
|
picker.Picker,
|
|
2800
3094
|
{
|
|
2801
3095
|
selectedValue: value ?? "",
|
|
@@ -2815,8 +3109,8 @@ function Select({
|
|
|
2815
3109
|
}
|
|
2816
3110
|
]
|
|
2817
3111
|
},
|
|
2818
|
-
/* @__PURE__ */
|
|
2819
|
-
options.map((o) => /* @__PURE__ */
|
|
3112
|
+
/* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", enabled: false }),
|
|
3113
|
+
options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
|
|
2820
3114
|
picker.Picker.Item,
|
|
2821
3115
|
{
|
|
2822
3116
|
key: o.value,
|
|
@@ -2825,7 +3119,7 @@ function Select({
|
|
|
2825
3119
|
enabled: !o.disabled
|
|
2826
3120
|
}
|
|
2827
3121
|
))
|
|
2828
|
-
) : null, error ? /* @__PURE__ */
|
|
3122
|
+
) : null, error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null);
|
|
2829
3123
|
}
|
|
2830
3124
|
var styles23 = reactNative.StyleSheet.create({
|
|
2831
3125
|
container: {
|
|
@@ -2906,7 +3200,7 @@ function useToast() {
|
|
|
2906
3200
|
function ToastProvider({ children }) {
|
|
2907
3201
|
const { colorScheme } = useTheme();
|
|
2908
3202
|
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
2909
|
-
return /* @__PURE__ */
|
|
3203
|
+
return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, children, /* @__PURE__ */ React25__default.default.createElement(
|
|
2910
3204
|
sonnerNative.Toaster,
|
|
2911
3205
|
{
|
|
2912
3206
|
theme: colorScheme,
|
|
@@ -2957,7 +3251,6 @@ function CurrencyInput({
|
|
|
2957
3251
|
containerStyle,
|
|
2958
3252
|
style
|
|
2959
3253
|
}) {
|
|
2960
|
-
const { colors } = useTheme();
|
|
2961
3254
|
const handleChange = (text) => {
|
|
2962
3255
|
const withoutPrefix = prefix && text.startsWith(prefix) ? text.slice(prefix.length) : text;
|
|
2963
3256
|
const formatted = formatCurrency(withoutPrefix, thousandsSeparator);
|
|
@@ -2967,10 +3260,14 @@ function CurrencyInput({
|
|
|
2967
3260
|
const raw = parseFloat(formatted.replace(separatorRegex, "") || "0");
|
|
2968
3261
|
onChangeValue?.(isNaN(raw) ? 0 : raw);
|
|
2969
3262
|
};
|
|
2970
|
-
const
|
|
2971
|
-
const
|
|
3263
|
+
const isLarge = size === "large";
|
|
3264
|
+
const inputStyle = isLarge ? { fontFamily: "Sohne-Regular", fontSize: ms(36) } : { fontFamily: "Sohne-Regular" };
|
|
3265
|
+
const prefixStyle = {
|
|
3266
|
+
fontFamily: "Sohne-Regular",
|
|
3267
|
+
fontSize: isLarge ? ms(32) : ms(17)
|
|
3268
|
+
};
|
|
2972
3269
|
const displayValue = value && prefix && value.startsWith(prefix) ? value.slice(prefix.length) : value;
|
|
2973
|
-
return /* @__PURE__ */
|
|
3270
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
2974
3271
|
Input,
|
|
2975
3272
|
{
|
|
2976
3273
|
value: displayValue,
|
|
@@ -2981,9 +3278,10 @@ function CurrencyInput({
|
|
|
2981
3278
|
hint,
|
|
2982
3279
|
placeholder: placeholder ?? "0",
|
|
2983
3280
|
editable,
|
|
2984
|
-
prefix
|
|
3281
|
+
prefix,
|
|
3282
|
+
prefixStyle,
|
|
2985
3283
|
containerStyle,
|
|
2986
|
-
inputWrapperStyle:
|
|
3284
|
+
inputWrapperStyle: isLarge ? { paddingVertical: vs(16), minHeight: 72 } : void 0,
|
|
2987
3285
|
style: [inputStyle, style]
|
|
2988
3286
|
}
|
|
2989
3287
|
);
|
|
@@ -3018,7 +3316,7 @@ function CurrencyDisplayBase({ value, prefix = "$", showDecimals = false, textCo
|
|
|
3018
3316
|
const baseFontSize = variant ? variantFontSize[variant] : ms(56);
|
|
3019
3317
|
const fontSize = maxFontSize ?? baseFontSize;
|
|
3020
3318
|
const letterSpacing = variant ? variantLetterSpacing[variant] : -2;
|
|
3021
|
-
return /* @__PURE__ */
|
|
3319
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles24.container, style] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3022
3320
|
reactNative.Text,
|
|
3023
3321
|
{
|
|
3024
3322
|
style: [styles24.amount, { color: textColor ?? colors.foreground, fontSize, letterSpacing }],
|
|
@@ -3030,7 +3328,7 @@ function CurrencyDisplayBase({ value, prefix = "$", showDecimals = false, textCo
|
|
|
3030
3328
|
formatted
|
|
3031
3329
|
));
|
|
3032
3330
|
}
|
|
3033
|
-
var CurrencyDisplay =
|
|
3331
|
+
var CurrencyDisplay = React25__default.default.memo(CurrencyDisplayBase);
|
|
3034
3332
|
var styles24 = reactNative.StyleSheet.create({
|
|
3035
3333
|
container: {
|
|
3036
3334
|
alignSelf: "flex-start"
|
|
@@ -3065,12 +3363,6 @@ function ListItemBase({
|
|
|
3065
3363
|
accessibilityLabel
|
|
3066
3364
|
}) {
|
|
3067
3365
|
const { colors } = useTheme();
|
|
3068
|
-
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3069
|
-
pressScale: PRESS_SCALE.row,
|
|
3070
|
-
pressInSpring: SPRINGS.surfacePressIn,
|
|
3071
|
-
pressOutSpring: SPRINGS.surfacePressOut,
|
|
3072
|
-
disabled: !onPress || disabled
|
|
3073
|
-
});
|
|
3074
3366
|
const handlePress = () => {
|
|
3075
3367
|
selectionAsync();
|
|
3076
3368
|
onPress?.();
|
|
@@ -3089,65 +3381,58 @@ function ListItemBase({
|
|
|
3089
3381
|
elevation: 2
|
|
3090
3382
|
} : {};
|
|
3091
3383
|
const a11yLabel = accessibilityLabel ?? [title, subtitle, caption].filter(Boolean).join(". ");
|
|
3092
|
-
|
|
3093
|
-
reactNative.
|
|
3384
|
+
const content = /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveLeft ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.leftContainer }, effectiveLeft) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.content }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3385
|
+
reactNative.Text,
|
|
3094
3386
|
{
|
|
3095
|
-
style: [styles25.
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
onPressOut,
|
|
3099
|
-
disabled,
|
|
3100
|
-
activeOpacity: 1,
|
|
3101
|
-
touchSoundDisabled: true,
|
|
3102
|
-
accessibilityRole: onPress ? "button" : void 0,
|
|
3103
|
-
accessibilityLabel: onPress ? a11yLabel : void 0,
|
|
3104
|
-
accessibilityState: onPress ? { disabled: !!disabled } : void 0
|
|
3387
|
+
style: [styles25.title, { color: colors.foreground }, titleStyle],
|
|
3388
|
+
numberOfLines: 2,
|
|
3389
|
+
allowFontScaling: true
|
|
3105
3390
|
},
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3391
|
+
title
|
|
3392
|
+
), subtitle ? /* @__PURE__ */ React25__default.default.createElement(
|
|
3393
|
+
reactNative.Text,
|
|
3394
|
+
{
|
|
3395
|
+
style: [styles25.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
|
|
3396
|
+
numberOfLines: 2,
|
|
3397
|
+
allowFontScaling: true
|
|
3398
|
+
},
|
|
3399
|
+
subtitle
|
|
3400
|
+
) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(
|
|
3401
|
+
reactNative.Text,
|
|
3402
|
+
{
|
|
3403
|
+
style: [styles25.caption, { color: colors.foregroundMuted }, captionStyle],
|
|
3404
|
+
numberOfLines: 1,
|
|
3405
|
+
allowFontScaling: true
|
|
3406
|
+
},
|
|
3407
|
+
caption
|
|
3408
|
+
) : null), effectiveRight !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof effectiveRight === "string" ? /* @__PURE__ */ React25__default.default.createElement(
|
|
3409
|
+
reactNative.Text,
|
|
3410
|
+
{
|
|
3411
|
+
style: [styles25.rightText, { color: colors.foregroundMuted }],
|
|
3412
|
+
allowFontScaling: true
|
|
3413
|
+
},
|
|
3414
|
+
effectiveRight
|
|
3415
|
+
) : effectiveRight) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.foregroundMuted }) : null);
|
|
3416
|
+
if (onPress) {
|
|
3417
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled && styles25.disabled }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3418
|
+
PressableRow,
|
|
3134
3419
|
{
|
|
3135
|
-
style: [styles25.
|
|
3136
|
-
|
|
3420
|
+
style: [styles25.container, cardStyle, style],
|
|
3421
|
+
onPress: handlePress,
|
|
3422
|
+
enabled: !disabled,
|
|
3423
|
+
rippleColor: "transparent",
|
|
3424
|
+
touchSoundDisabled: true,
|
|
3425
|
+
activateOnHover: true,
|
|
3426
|
+
accessibilityRole: "button",
|
|
3427
|
+
accessibilityLabel: a11yLabel,
|
|
3428
|
+
accessibilityState: { disabled: !!disabled }
|
|
3137
3429
|
},
|
|
3138
|
-
|
|
3139
|
-
)
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
{
|
|
3143
|
-
style: [
|
|
3144
|
-
styles25.separator,
|
|
3145
|
-
{ backgroundColor: colors.separator }
|
|
3146
|
-
]
|
|
3147
|
-
}
|
|
3148
|
-
) : null);
|
|
3430
|
+
content
|
|
3431
|
+
), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles25.separator, { backgroundColor: colors.separator }] }) : null);
|
|
3432
|
+
}
|
|
3433
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [disabled && styles25.disabled] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles25.container, cardStyle, style] }, content), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles25.separator, { backgroundColor: colors.separator }] }) : null);
|
|
3149
3434
|
}
|
|
3150
|
-
var ListItem =
|
|
3435
|
+
var ListItem = React25__default.default.memo(ListItemBase);
|
|
3151
3436
|
var styles25 = reactNative.StyleSheet.create({
|
|
3152
3437
|
container: {
|
|
3153
3438
|
flexDirection: "row",
|
|
@@ -3203,17 +3488,17 @@ var styles25 = reactNative.StyleSheet.create({
|
|
|
3203
3488
|
});
|
|
3204
3489
|
function ListGroup({ children, variant = "plain", style }) {
|
|
3205
3490
|
const { colors } = useTheme();
|
|
3206
|
-
const processedChildren =
|
|
3207
|
-
if (!
|
|
3491
|
+
const processedChildren = React25__default.default.Children.map(children, (child, index) => {
|
|
3492
|
+
if (!React25__default.default.isValidElement(child)) return child;
|
|
3208
3493
|
if (child.type === ListGroupHeader || child.type === ListGroupFooter) {
|
|
3209
3494
|
return child;
|
|
3210
3495
|
}
|
|
3211
3496
|
const childProps = child.props;
|
|
3212
3497
|
const isListItem = "title" in childProps;
|
|
3213
3498
|
if (!isListItem) return child;
|
|
3214
|
-
const isLast = index ===
|
|
3499
|
+
const isLast = index === React25__default.default.Children.count(children) - 1;
|
|
3215
3500
|
if (childProps["showSeparator"] === void 0 && !isLast) {
|
|
3216
|
-
return
|
|
3501
|
+
return React25__default.default.cloneElement(child, {
|
|
3217
3502
|
showSeparator: true
|
|
3218
3503
|
});
|
|
3219
3504
|
}
|
|
@@ -3231,21 +3516,21 @@ function ListGroup({ children, variant = "plain", style }) {
|
|
|
3231
3516
|
elevation: 2,
|
|
3232
3517
|
paddingVertical: vs(4)
|
|
3233
3518
|
} : {};
|
|
3234
|
-
return /* @__PURE__ */
|
|
3519
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.container, cardStyle, style] }, processedChildren);
|
|
3235
3520
|
}
|
|
3236
3521
|
function ListGroupHeader({ children, style }) {
|
|
3237
3522
|
const { colors } = useTheme();
|
|
3238
3523
|
if (typeof children === "string") {
|
|
3239
|
-
return /* @__PURE__ */
|
|
3524
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.header, { borderBottomColor: colors.separator }, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles26.headerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
|
|
3240
3525
|
}
|
|
3241
|
-
return /* @__PURE__ */
|
|
3526
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.header, { borderBottomColor: colors.separator }, style] }, children);
|
|
3242
3527
|
}
|
|
3243
3528
|
function ListGroupFooter({ children, style }) {
|
|
3244
3529
|
const { colors } = useTheme();
|
|
3245
3530
|
if (typeof children === "string") {
|
|
3246
|
-
return /* @__PURE__ */
|
|
3531
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.footer, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles26.footerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
|
|
3247
3532
|
}
|
|
3248
|
-
return /* @__PURE__ */
|
|
3533
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.footer, style] }, children);
|
|
3249
3534
|
}
|
|
3250
3535
|
ListGroup.Header = ListGroupHeader;
|
|
3251
3536
|
ListGroup.Footer = ListGroupFooter;
|
|
@@ -3292,12 +3577,6 @@ function MenuItemBase({
|
|
|
3292
3577
|
accessibilityLabel
|
|
3293
3578
|
}) {
|
|
3294
3579
|
const { colors } = useTheme();
|
|
3295
|
-
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3296
|
-
pressScale: PRESS_SCALE.row,
|
|
3297
|
-
pressInSpring: SPRINGS.surfacePressIn,
|
|
3298
|
-
pressOutSpring: SPRINGS.surfacePressOut,
|
|
3299
|
-
disabled
|
|
3300
|
-
});
|
|
3301
3580
|
const handlePress = () => {
|
|
3302
3581
|
selectionAsync();
|
|
3303
3582
|
onPress();
|
|
@@ -3315,22 +3594,21 @@ function MenuItemBase({
|
|
|
3315
3594
|
elevation: 2
|
|
3316
3595
|
} : {};
|
|
3317
3596
|
const a11yLabel = accessibilityLabel ?? (subtitle ? `${label}. ${subtitle}` : label);
|
|
3318
|
-
return /* @__PURE__ */
|
|
3319
|
-
|
|
3597
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled && styles27.disabled }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3598
|
+
PressableRow,
|
|
3320
3599
|
{
|
|
3321
3600
|
style: [styles27.container, cardStyle, style],
|
|
3322
3601
|
onPress: handlePress,
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
disabled,
|
|
3326
|
-
activeOpacity: 1,
|
|
3602
|
+
enabled: !disabled,
|
|
3603
|
+
rippleColor: "transparent",
|
|
3327
3604
|
touchSoundDisabled: true,
|
|
3605
|
+
activateOnHover: true,
|
|
3328
3606
|
accessibilityRole: "button",
|
|
3329
3607
|
accessibilityLabel: a11yLabel,
|
|
3330
3608
|
accessibilityState: { disabled }
|
|
3331
3609
|
},
|
|
3332
|
-
resolvedIcon ? /* @__PURE__ */
|
|
3333
|
-
/* @__PURE__ */
|
|
3610
|
+
resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles27.iconContainer }, resolvedIcon) : null,
|
|
3611
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles27.labelContainer }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3334
3612
|
reactNative.Text,
|
|
3335
3613
|
{
|
|
3336
3614
|
style: [styles27.label, { color: colors.foreground }, labelStyle],
|
|
@@ -3338,7 +3616,7 @@ function MenuItemBase({
|
|
|
3338
3616
|
allowFontScaling: true
|
|
3339
3617
|
},
|
|
3340
3618
|
label
|
|
3341
|
-
), subtitle ? /* @__PURE__ */
|
|
3619
|
+
), subtitle ? /* @__PURE__ */ React25__default.default.createElement(
|
|
3342
3620
|
reactNative.Text,
|
|
3343
3621
|
{
|
|
3344
3622
|
style: [styles27.subtitle, { color: colors.foregroundMuted }],
|
|
@@ -3347,7 +3625,7 @@ function MenuItemBase({
|
|
|
3347
3625
|
},
|
|
3348
3626
|
subtitle
|
|
3349
3627
|
) : null),
|
|
3350
|
-
rightRender !== void 0 ? /* @__PURE__ */
|
|
3628
|
+
rightRender !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(
|
|
3351
3629
|
reactNative.View,
|
|
3352
3630
|
{
|
|
3353
3631
|
style: styles27.rightContainer,
|
|
@@ -3356,18 +3634,10 @@ function MenuItemBase({
|
|
|
3356
3634
|
}
|
|
3357
3635
|
},
|
|
3358
3636
|
rightRender
|
|
3359
|
-
) : showChevron ? /* @__PURE__ */
|
|
3360
|
-
), showSeparator ? /* @__PURE__ */
|
|
3361
|
-
reactNative.View,
|
|
3362
|
-
{
|
|
3363
|
-
style: [
|
|
3364
|
-
styles27.separator,
|
|
3365
|
-
{ backgroundColor: colors.separator }
|
|
3366
|
-
]
|
|
3367
|
-
}
|
|
3368
|
-
) : null);
|
|
3637
|
+
) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-right", size: 18, color: colors.foregroundMuted }) : null
|
|
3638
|
+
), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles27.separator, { backgroundColor: colors.separator }] }) : null);
|
|
3369
3639
|
}
|
|
3370
|
-
var MenuItem =
|
|
3640
|
+
var MenuItem = React25__default.default.memo(MenuItemBase);
|
|
3371
3641
|
var styles27 = reactNative.StyleSheet.create({
|
|
3372
3642
|
container: {
|
|
3373
3643
|
flexDirection: "row",
|
|
@@ -3411,17 +3681,17 @@ var styles27 = reactNative.StyleSheet.create({
|
|
|
3411
3681
|
});
|
|
3412
3682
|
function MenuGroup({ children, variant = "plain", style }) {
|
|
3413
3683
|
const { colors } = useTheme();
|
|
3414
|
-
const processedChildren =
|
|
3415
|
-
if (!
|
|
3684
|
+
const processedChildren = React25__default.default.Children.map(children, (child, index) => {
|
|
3685
|
+
if (!React25__default.default.isValidElement(child)) return child;
|
|
3416
3686
|
if (child.type === MenuGroupHeader || child.type === MenuGroupFooter) {
|
|
3417
3687
|
return child;
|
|
3418
3688
|
}
|
|
3419
3689
|
const childProps = child.props;
|
|
3420
3690
|
const isMenuItem = "onPress" in childProps;
|
|
3421
3691
|
if (!isMenuItem) return child;
|
|
3422
|
-
const isLast = index ===
|
|
3692
|
+
const isLast = index === React25__default.default.Children.count(children) - 1;
|
|
3423
3693
|
if (childProps["showSeparator"] === void 0 && !isLast) {
|
|
3424
|
-
return
|
|
3694
|
+
return React25__default.default.cloneElement(child, {
|
|
3425
3695
|
showSeparator: true
|
|
3426
3696
|
});
|
|
3427
3697
|
}
|
|
@@ -3439,21 +3709,21 @@ function MenuGroup({ children, variant = "plain", style }) {
|
|
|
3439
3709
|
elevation: 2,
|
|
3440
3710
|
paddingVertical: vs(4)
|
|
3441
3711
|
} : {};
|
|
3442
|
-
return /* @__PURE__ */
|
|
3712
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.container, cardStyle, style] }, processedChildren);
|
|
3443
3713
|
}
|
|
3444
3714
|
function MenuGroupHeader({ children, style }) {
|
|
3445
3715
|
const { colors } = useTheme();
|
|
3446
3716
|
if (typeof children === "string") {
|
|
3447
|
-
return /* @__PURE__ */
|
|
3717
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.header, { borderBottomColor: colors.separator }, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.headerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
|
|
3448
3718
|
}
|
|
3449
|
-
return /* @__PURE__ */
|
|
3719
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.header, { borderBottomColor: colors.separator }, style] }, children);
|
|
3450
3720
|
}
|
|
3451
3721
|
function MenuGroupFooter({ children, style }) {
|
|
3452
3722
|
const { colors } = useTheme();
|
|
3453
3723
|
if (typeof children === "string") {
|
|
3454
|
-
return /* @__PURE__ */
|
|
3724
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.footer, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.footerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
|
|
3455
3725
|
}
|
|
3456
|
-
return /* @__PURE__ */
|
|
3726
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.footer, style] }, children);
|
|
3457
3727
|
}
|
|
3458
3728
|
MenuGroup.Header = MenuGroupHeader;
|
|
3459
3729
|
MenuGroup.Footer = MenuGroupFooter;
|
|
@@ -3485,38 +3755,44 @@ var styles28 = reactNative.StyleSheet.create({
|
|
|
3485
3755
|
});
|
|
3486
3756
|
function ChipBase({ label, selected = false, onPress, icon, iconName, style, accessibilityLabel }) {
|
|
3487
3757
|
const { colors } = useTheme();
|
|
3488
|
-
const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3489
|
-
pressScale: PRESS_SCALE.chip
|
|
3490
|
-
});
|
|
3491
|
-
const colorProgress = useColorTransition(selected);
|
|
3492
|
-
const surfaceStyle = Animated9.useAnimatedStyle(() => ({
|
|
3493
|
-
backgroundColor: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.surface, colors.primary]),
|
|
3494
|
-
borderColor: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.border, colors.primary])
|
|
3495
|
-
}));
|
|
3496
|
-
const textStyle = Animated9.useAnimatedStyle(() => ({
|
|
3497
|
-
color: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.foreground, colors.primaryForeground])
|
|
3498
|
-
}));
|
|
3499
3758
|
const handlePress = () => {
|
|
3500
3759
|
selectionAsync();
|
|
3501
3760
|
onPress?.();
|
|
3502
3761
|
};
|
|
3503
3762
|
const resolvedIcon = iconName ? renderIcon(iconName, ms(13), selected ? colors.primaryForeground : colors.foreground) : icon;
|
|
3504
|
-
return /* @__PURE__ */
|
|
3505
|
-
|
|
3763
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles29.wrapper, style] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3764
|
+
PressableChip,
|
|
3506
3765
|
{
|
|
3507
3766
|
onPress: handlePress,
|
|
3508
|
-
|
|
3509
|
-
onPressOut,
|
|
3510
|
-
activeOpacity: 1,
|
|
3767
|
+
rippleColor: "transparent",
|
|
3511
3768
|
touchSoundDisabled: true,
|
|
3512
3769
|
accessibilityRole: "button",
|
|
3513
3770
|
accessibilityLabel: accessibilityLabel ?? label,
|
|
3514
3771
|
accessibilityState: { selected }
|
|
3515
3772
|
},
|
|
3516
|
-
/* @__PURE__ */
|
|
3773
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
3774
|
+
reactNativeEase.EaseView,
|
|
3775
|
+
{
|
|
3776
|
+
style: styles29.chip,
|
|
3777
|
+
animate: {
|
|
3778
|
+
backgroundColor: selected ? colors.primary : colors.surface,
|
|
3779
|
+
borderColor: selected ? colors.primary : colors.border
|
|
3780
|
+
},
|
|
3781
|
+
transition: COLOR_TRANSITION
|
|
3782
|
+
},
|
|
3783
|
+
resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles29.chipIcon }, resolvedIcon) : null,
|
|
3784
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
3785
|
+
reactNative.Text,
|
|
3786
|
+
{
|
|
3787
|
+
style: [styles29.label, { color: selected ? colors.primaryForeground : colors.foreground }],
|
|
3788
|
+
allowFontScaling: true
|
|
3789
|
+
},
|
|
3790
|
+
label
|
|
3791
|
+
)
|
|
3792
|
+
)
|
|
3517
3793
|
));
|
|
3518
3794
|
}
|
|
3519
|
-
var Chip =
|
|
3795
|
+
var Chip = React25__default.default.memo(ChipBase);
|
|
3520
3796
|
function ChipGroup({ options, value, onValueChange, multiSelect = false, style }) {
|
|
3521
3797
|
const handlePress = (optionValue) => {
|
|
3522
3798
|
if (!multiSelect) {
|
|
@@ -3524,20 +3800,20 @@ function ChipGroup({ options, value, onValueChange, multiSelect = false, style }
|
|
|
3524
3800
|
return;
|
|
3525
3801
|
}
|
|
3526
3802
|
const currentArray = Array.isArray(value) ? value : value ? [value] : [];
|
|
3527
|
-
const
|
|
3528
|
-
const newArray =
|
|
3803
|
+
const isSelected3 = currentArray.includes(optionValue);
|
|
3804
|
+
const newArray = isSelected3 ? currentArray.filter((v) => v !== optionValue) : [...currentArray, optionValue];
|
|
3529
3805
|
onValueChange?.(newArray);
|
|
3530
3806
|
};
|
|
3531
|
-
const
|
|
3807
|
+
const isSelected2 = (optionValue) => {
|
|
3532
3808
|
if (Array.isArray(value)) return value.includes(optionValue);
|
|
3533
3809
|
return optionValue === value;
|
|
3534
3810
|
};
|
|
3535
|
-
return /* @__PURE__ */
|
|
3811
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles29.group, style] }, options.map((opt) => /* @__PURE__ */ React25__default.default.createElement(
|
|
3536
3812
|
Chip,
|
|
3537
3813
|
{
|
|
3538
3814
|
key: opt.value,
|
|
3539
3815
|
label: opt.label,
|
|
3540
|
-
selected:
|
|
3816
|
+
selected: isSelected2(opt.value),
|
|
3541
3817
|
onPress: opt.disabled ? void 0 : () => handlePress(opt.value),
|
|
3542
3818
|
iconName: opt.iconName,
|
|
3543
3819
|
style: opt.disabled ? styles29.chipDisabled : void 0,
|
|
@@ -3589,8 +3865,8 @@ function ConfirmDialog({
|
|
|
3589
3865
|
onCancel
|
|
3590
3866
|
}) {
|
|
3591
3867
|
const { colors } = useTheme();
|
|
3592
|
-
const ref =
|
|
3593
|
-
|
|
3868
|
+
const ref = React25.useRef(null);
|
|
3869
|
+
React25.useEffect(() => {
|
|
3594
3870
|
if (visible) {
|
|
3595
3871
|
impactMedium();
|
|
3596
3872
|
ref.current?.present();
|
|
@@ -3598,7 +3874,7 @@ function ConfirmDialog({
|
|
|
3598
3874
|
ref.current?.dismiss();
|
|
3599
3875
|
}
|
|
3600
3876
|
}, [visible]);
|
|
3601
|
-
const renderBackdrop = (props) => /* @__PURE__ */
|
|
3877
|
+
const renderBackdrop = (props) => /* @__PURE__ */ React25__default.default.createElement(
|
|
3602
3878
|
bottomSheet.BottomSheetBackdrop,
|
|
3603
3879
|
{
|
|
3604
3880
|
...props,
|
|
@@ -3607,7 +3883,7 @@ function ConfirmDialog({
|
|
|
3607
3883
|
pressBehavior: "close"
|
|
3608
3884
|
}
|
|
3609
3885
|
);
|
|
3610
|
-
return /* @__PURE__ */
|
|
3886
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
3611
3887
|
bottomSheet.BottomSheetModal,
|
|
3612
3888
|
{
|
|
3613
3889
|
ref,
|
|
@@ -3618,7 +3894,7 @@ function ConfirmDialog({
|
|
|
3618
3894
|
handleIndicatorStyle: [styles30.handle, { backgroundColor: colors.border }],
|
|
3619
3895
|
enablePanDownToClose: true
|
|
3620
3896
|
},
|
|
3621
|
-
/* @__PURE__ */
|
|
3897
|
+
/* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: styles30.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles30.actions }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3622
3898
|
Button,
|
|
3623
3899
|
{
|
|
3624
3900
|
label: confirmLabel,
|
|
@@ -3628,7 +3904,7 @@ function ConfirmDialog({
|
|
|
3628
3904
|
notificationSuccess();
|
|
3629
3905
|
onConfirm();
|
|
3630
3906
|
},
|
|
3631
|
-
icon: /* @__PURE__ */
|
|
3907
|
+
icon: /* @__PURE__ */ React25__default.default.createElement(
|
|
3632
3908
|
vectorIcons.Feather,
|
|
3633
3909
|
{
|
|
3634
3910
|
name: confirmVariant === "destructive" ? "trash-2" : "check",
|
|
@@ -3637,7 +3913,7 @@ function ConfirmDialog({
|
|
|
3637
3913
|
}
|
|
3638
3914
|
)
|
|
3639
3915
|
}
|
|
3640
|
-
), /* @__PURE__ */
|
|
3916
|
+
), /* @__PURE__ */ React25__default.default.createElement(
|
|
3641
3917
|
Button,
|
|
3642
3918
|
{
|
|
3643
3919
|
label: cancelLabel,
|
|
@@ -3647,7 +3923,7 @@ function ConfirmDialog({
|
|
|
3647
3923
|
selectionAsync();
|
|
3648
3924
|
onCancel();
|
|
3649
3925
|
},
|
|
3650
|
-
icon: /* @__PURE__ */
|
|
3926
|
+
icon: /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: 15, color: colors.foreground })
|
|
3651
3927
|
}
|
|
3652
3928
|
)))
|
|
3653
3929
|
);
|
|
@@ -3685,9 +3961,9 @@ var styles30 = reactNative.StyleSheet.create({
|
|
|
3685
3961
|
function LabelValueBase({ label, value, iconName, iconColor, style }) {
|
|
3686
3962
|
const { colors } = useTheme();
|
|
3687
3963
|
const resolvedIcon = iconName ? renderIcon(iconName, ms(14), iconColor ?? colors.foregroundMuted) : null;
|
|
3688
|
-
return /* @__PURE__ */
|
|
3964
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles31.container, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles31.labelSide }, resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles31.icon }, resolvedIcon) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.label, { color: colors.foregroundMuted }], allowFontScaling: true }, label)), typeof value === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
|
|
3689
3965
|
}
|
|
3690
|
-
var LabelValue =
|
|
3966
|
+
var LabelValue = React25__default.default.memo(LabelValueBase);
|
|
3691
3967
|
var styles31 = reactNative.StyleSheet.create({
|
|
3692
3968
|
container: {
|
|
3693
3969
|
flexDirection: "row",
|
|
@@ -3722,42 +3998,51 @@ var MONTH_NAMES = {
|
|
|
3722
3998
|
pt: ["janeiro", "fevereiro", "mar\xE7o", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"],
|
|
3723
3999
|
fr: ["janvier", "f\xE9vrier", "mars", "avril", "mai", "juin", "juillet", "ao\xFBt", "septembre", "octobre", "novembre", "d\xE9cembre"]
|
|
3724
4000
|
};
|
|
3725
|
-
function
|
|
4001
|
+
function dateToMonthPickerValue(date) {
|
|
4002
|
+
return { month: date.getMonth() + 1, year: date.getFullYear() };
|
|
4003
|
+
}
|
|
4004
|
+
function monthPickerValueToDate(value) {
|
|
4005
|
+
return new Date(value.year, value.month - 1, 1);
|
|
4006
|
+
}
|
|
4007
|
+
var toIndex = (v) => v.year * 12 + (v.month - 1);
|
|
4008
|
+
var fromIndex = (i) => ({ year: Math.floor(i / 12), month: i % 12 + 1 });
|
|
4009
|
+
function MonthPicker({ value, onChange, minValue, maxValue, locale = "en", formatLabel, style }) {
|
|
3726
4010
|
const { colors } = useTheme();
|
|
4011
|
+
const index = toIndex(value);
|
|
4012
|
+
const minIndex = minValue ? toIndex(minValue) : -Infinity;
|
|
4013
|
+
const maxIndex = maxValue ? toIndex(maxValue) : Infinity;
|
|
4014
|
+
const prevDisabled = index - 1 < minIndex;
|
|
4015
|
+
const nextDisabled = index + 1 > maxIndex;
|
|
3727
4016
|
const getLabel = () => {
|
|
3728
4017
|
if (formatLabel) return formatLabel(value);
|
|
3729
4018
|
const names = MONTH_NAMES[locale] ?? MONTH_NAMES.en;
|
|
3730
4019
|
return `${names[value.month - 1]} ${value.year}`;
|
|
3731
4020
|
};
|
|
3732
4021
|
const handlePrev = () => {
|
|
4022
|
+
if (prevDisabled) return;
|
|
3733
4023
|
selectionAsync();
|
|
3734
|
-
|
|
3735
|
-
onChange({ month: 12, year: value.year - 1 });
|
|
3736
|
-
} else {
|
|
3737
|
-
onChange({ month: value.month - 1, year: value.year });
|
|
3738
|
-
}
|
|
4024
|
+
onChange(fromIndex(index - 1));
|
|
3739
4025
|
};
|
|
3740
4026
|
const handleNext = () => {
|
|
4027
|
+
if (nextDisabled) return;
|
|
3741
4028
|
selectionAsync();
|
|
3742
|
-
|
|
3743
|
-
onChange({ month: 1, year: value.year + 1 });
|
|
3744
|
-
} else {
|
|
3745
|
-
onChange({ month: value.month + 1, year: value.year });
|
|
3746
|
-
}
|
|
4029
|
+
onChange(fromIndex(index + 1));
|
|
3747
4030
|
};
|
|
3748
|
-
return /* @__PURE__ */
|
|
4031
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles32.container, style], accessibilityRole: "adjustable", accessibilityLabel: getLabel() }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3749
4032
|
reactNative.TouchableOpacity,
|
|
3750
4033
|
{
|
|
3751
|
-
style: styles32.arrow,
|
|
4034
|
+
style: [styles32.arrow, prevDisabled && styles32.arrowDisabled],
|
|
3752
4035
|
onPress: handlePrev,
|
|
4036
|
+
disabled: prevDisabled,
|
|
3753
4037
|
activeOpacity: 0.6,
|
|
3754
4038
|
touchSoundDisabled: true,
|
|
3755
4039
|
accessibilityRole: "button",
|
|
3756
4040
|
accessibilityLabel: "Previous month",
|
|
4041
|
+
accessibilityState: { disabled: prevDisabled },
|
|
3757
4042
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
|
|
3758
4043
|
},
|
|
3759
|
-
/* @__PURE__ */
|
|
3760
|
-
), /* @__PURE__ */
|
|
4044
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-left", size: 22, color: colors.foreground })
|
|
4045
|
+
), /* @__PURE__ */ React25__default.default.createElement(
|
|
3761
4046
|
reactNative.Text,
|
|
3762
4047
|
{
|
|
3763
4048
|
style: [styles32.label, { color: colors.foreground }],
|
|
@@ -3765,18 +4050,20 @@ function MonthPicker({ value, onChange, locale = "en", formatLabel, style }) {
|
|
|
3765
4050
|
accessibilityLiveRegion: "polite"
|
|
3766
4051
|
},
|
|
3767
4052
|
getLabel()
|
|
3768
|
-
), /* @__PURE__ */
|
|
4053
|
+
), /* @__PURE__ */ React25__default.default.createElement(
|
|
3769
4054
|
reactNative.TouchableOpacity,
|
|
3770
4055
|
{
|
|
3771
|
-
style: styles32.arrow,
|
|
4056
|
+
style: [styles32.arrow, nextDisabled && styles32.arrowDisabled],
|
|
3772
4057
|
onPress: handleNext,
|
|
4058
|
+
disabled: nextDisabled,
|
|
3773
4059
|
activeOpacity: 0.6,
|
|
3774
4060
|
touchSoundDisabled: true,
|
|
3775
4061
|
accessibilityRole: "button",
|
|
3776
4062
|
accessibilityLabel: "Next month",
|
|
4063
|
+
accessibilityState: { disabled: nextDisabled },
|
|
3777
4064
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
|
|
3778
4065
|
},
|
|
3779
|
-
/* @__PURE__ */
|
|
4066
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-right", size: 22, color: colors.foreground })
|
|
3780
4067
|
));
|
|
3781
4068
|
}
|
|
3782
4069
|
var styles32 = reactNative.StyleSheet.create({
|
|
@@ -3791,6 +4078,9 @@ var styles32 = reactNative.StyleSheet.create({
|
|
|
3791
4078
|
alignItems: "center",
|
|
3792
4079
|
justifyContent: "center"
|
|
3793
4080
|
},
|
|
4081
|
+
arrowDisabled: {
|
|
4082
|
+
opacity: 0.3
|
|
4083
|
+
},
|
|
3794
4084
|
label: {
|
|
3795
4085
|
fontFamily: "Sohne-Medium",
|
|
3796
4086
|
fontSize: ms(17),
|
|
@@ -3799,7 +4089,7 @@ var styles32 = reactNative.StyleSheet.create({
|
|
|
3799
4089
|
minWidth: s(160)
|
|
3800
4090
|
}
|
|
3801
4091
|
});
|
|
3802
|
-
var
|
|
4092
|
+
var aspectRatioMap2 = {
|
|
3803
4093
|
"1:1": 1,
|
|
3804
4094
|
"4:3": 3 / 4,
|
|
3805
4095
|
"16:9": 9 / 16,
|
|
@@ -3836,10 +4126,10 @@ function MediaCardBase({
|
|
|
3836
4126
|
impactLight();
|
|
3837
4127
|
onPress();
|
|
3838
4128
|
};
|
|
3839
|
-
const ratio =
|
|
4129
|
+
const ratio = aspectRatioMap2[aspectRatio];
|
|
3840
4130
|
const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
|
|
3841
4131
|
const a11yLabel = accessibilityLabel ?? [title, subtitle].filter(Boolean).join(". ");
|
|
3842
|
-
const cardContent = /* @__PURE__ */
|
|
4132
|
+
const cardContent = /* @__PURE__ */ React25__default.default.createElement(
|
|
3843
4133
|
reactNative.View,
|
|
3844
4134
|
{
|
|
3845
4135
|
style: [
|
|
@@ -3849,33 +4139,34 @@ function MediaCardBase({
|
|
|
3849
4139
|
],
|
|
3850
4140
|
...reactNative.Platform.OS === "web" ? hoverHandlers : {}
|
|
3851
4141
|
},
|
|
3852
|
-
/* @__PURE__ */
|
|
4142
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles33.imageContainer, imageStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React25__default.default.createElement(
|
|
3853
4143
|
reactNative.Image,
|
|
3854
4144
|
{
|
|
3855
4145
|
source: imageSource,
|
|
3856
4146
|
style: styles33.image,
|
|
3857
4147
|
resizeMode: "cover"
|
|
3858
4148
|
}
|
|
3859
|
-
) : /* @__PURE__ */
|
|
4149
|
+
) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles33.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles33.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React25__default.default.createElement(
|
|
3860
4150
|
reactNative.TouchableOpacity,
|
|
3861
4151
|
{
|
|
3862
4152
|
style: [styles33.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
|
|
3863
|
-
onPress: () => {
|
|
4153
|
+
onPress: (e) => {
|
|
4154
|
+
e?.stopPropagation?.();
|
|
3864
4155
|
impactLight();
|
|
3865
4156
|
onActionPress?.();
|
|
3866
4157
|
},
|
|
3867
4158
|
activeOpacity: 0.8,
|
|
3868
4159
|
touchSoundDisabled: true,
|
|
3869
|
-
accessibilityRole: "button",
|
|
4160
|
+
accessibilityRole: reactNative.Platform.OS === "web" && onPress ? void 0 : "button",
|
|
3870
4161
|
accessibilityLabel: actionIconName ?? "action",
|
|
3871
4162
|
accessibilityState: { selected: actionActive }
|
|
3872
4163
|
},
|
|
3873
4164
|
resolvedActionIcon
|
|
3874
4165
|
)),
|
|
3875
|
-
(title || subtitle || caption || footer) && /* @__PURE__ */
|
|
4166
|
+
(title || subtitle || caption || footer) && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles33.meta }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles33.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles33.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles33.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
|
|
3876
4167
|
);
|
|
3877
4168
|
if (onPress) {
|
|
3878
|
-
return /* @__PURE__ */
|
|
4169
|
+
return /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: animatedStyle }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3879
4170
|
reactNative.TouchableOpacity,
|
|
3880
4171
|
{
|
|
3881
4172
|
onPress: handlePress,
|
|
@@ -3891,7 +4182,7 @@ function MediaCardBase({
|
|
|
3891
4182
|
}
|
|
3892
4183
|
return cardContent;
|
|
3893
4184
|
}
|
|
3894
|
-
var MediaCard =
|
|
4185
|
+
var MediaCard = React25__default.default.memo(MediaCardBase);
|
|
3895
4186
|
var styles33 = reactNative.StyleSheet.create({
|
|
3896
4187
|
card: {
|
|
3897
4188
|
borderRadius: RADIUS.md,
|
|
@@ -3949,7 +4240,7 @@ var styles33 = reactNative.StyleSheet.create({
|
|
|
3949
4240
|
lineHeight: mvs(16)
|
|
3950
4241
|
}
|
|
3951
4242
|
});
|
|
3952
|
-
var CategoryChip =
|
|
4243
|
+
var CategoryChip = React25__default.default.memo(function CategoryChip2({
|
|
3953
4244
|
item,
|
|
3954
4245
|
selected,
|
|
3955
4246
|
onSelect
|
|
@@ -3958,17 +4249,9 @@ var CategoryChip = React26__default.default.memo(function CategoryChip2({
|
|
|
3958
4249
|
const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
3959
4250
|
pressScale: PRESS_SCALE.chip
|
|
3960
4251
|
});
|
|
3961
|
-
const progress = useColorTransition(selected);
|
|
3962
|
-
const surfaceStyle = Animated9.useAnimatedStyle(() => ({
|
|
3963
|
-
backgroundColor: Animated9.interpolateColor(progress.value, [0, 1], [colors.surface, colors.primary]),
|
|
3964
|
-
borderColor: Animated9.interpolateColor(progress.value, [0, 1], [colors.border, colors.primary])
|
|
3965
|
-
}));
|
|
3966
|
-
const textColorStyle = Animated9.useAnimatedStyle(() => ({
|
|
3967
|
-
color: Animated9.interpolateColor(progress.value, [0, 1], [colors.foregroundSubtle, colors.primaryForeground])
|
|
3968
|
-
}));
|
|
3969
4252
|
const iconColor = selected ? colors.primaryForeground : colors.foregroundSubtle;
|
|
3970
4253
|
const resolvedIcon = typeof item.icon === "string" ? renderIcon(item.icon, 16, iconColor) : item.icon ?? null;
|
|
3971
|
-
return /* @__PURE__ */
|
|
4254
|
+
return /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: scaleStyle, ...hoverHandlers }, /* @__PURE__ */ React25__default.default.createElement(
|
|
3972
4255
|
reactNative.TouchableOpacity,
|
|
3973
4256
|
{
|
|
3974
4257
|
onPress: () => onSelect(item.value),
|
|
@@ -3980,7 +4263,27 @@ var CategoryChip = React26__default.default.memo(function CategoryChip2({
|
|
|
3980
4263
|
accessibilityLabel: item.label,
|
|
3981
4264
|
accessibilityState: { selected }
|
|
3982
4265
|
},
|
|
3983
|
-
/* @__PURE__ */
|
|
4266
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
4267
|
+
reactNativeEase.EaseView,
|
|
4268
|
+
{
|
|
4269
|
+
style: styles34.chip,
|
|
4270
|
+
animate: {
|
|
4271
|
+
backgroundColor: selected ? colors.primary : colors.surface,
|
|
4272
|
+
borderColor: selected ? colors.primary : colors.border
|
|
4273
|
+
},
|
|
4274
|
+
transition: COLOR_TRANSITION
|
|
4275
|
+
},
|
|
4276
|
+
resolvedIcon && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles34.chipIcon }, resolvedIcon),
|
|
4277
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
4278
|
+
reactNative.Text,
|
|
4279
|
+
{
|
|
4280
|
+
style: [styles34.chipLabel, { color: selected ? colors.primaryForeground : colors.foregroundSubtle }],
|
|
4281
|
+
allowFontScaling: true
|
|
4282
|
+
},
|
|
4283
|
+
item.label
|
|
4284
|
+
),
|
|
4285
|
+
item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles34.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles34.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99)))
|
|
4286
|
+
)
|
|
3984
4287
|
));
|
|
3985
4288
|
});
|
|
3986
4289
|
function CategoryStrip({
|
|
@@ -3993,7 +4296,7 @@ function CategoryStrip({
|
|
|
3993
4296
|
accessibilityLabel
|
|
3994
4297
|
}) {
|
|
3995
4298
|
const selected = Array.isArray(value) ? value : value ? [value] : [];
|
|
3996
|
-
const handlePress =
|
|
4299
|
+
const handlePress = React25.useCallback(
|
|
3997
4300
|
(v) => {
|
|
3998
4301
|
selectionAsync();
|
|
3999
4302
|
if (multiSelect) {
|
|
@@ -4006,7 +4309,7 @@ function CategoryStrip({
|
|
|
4006
4309
|
},
|
|
4007
4310
|
[multiSelect, value, onValueChange]
|
|
4008
4311
|
);
|
|
4009
|
-
return /* @__PURE__ */
|
|
4312
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4010
4313
|
reactNative.ScrollView,
|
|
4011
4314
|
{
|
|
4012
4315
|
horizontal: true,
|
|
@@ -4016,7 +4319,7 @@ function CategoryStrip({
|
|
|
4016
4319
|
accessibilityRole: multiSelect ? void 0 : "radiogroup",
|
|
4017
4320
|
accessibilityLabel
|
|
4018
4321
|
},
|
|
4019
|
-
categories.map((cat) => /* @__PURE__ */
|
|
4322
|
+
categories.map((cat) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: cat.value, style: itemStyle }, /* @__PURE__ */ React25__default.default.createElement(
|
|
4020
4323
|
CategoryChip,
|
|
4021
4324
|
{
|
|
4022
4325
|
item: cat,
|
|
@@ -4067,49 +4370,33 @@ var styles34 = reactNative.StyleSheet.create({
|
|
|
4067
4370
|
lineHeight: 14
|
|
4068
4371
|
}
|
|
4069
4372
|
});
|
|
4070
|
-
function
|
|
4373
|
+
function Pressable3({
|
|
4071
4374
|
children,
|
|
4072
4375
|
onPress,
|
|
4073
|
-
pressScale = PRESS_SCALE.card,
|
|
4376
|
+
pressScale: _pressScale = PRESS_SCALE.card,
|
|
4074
4377
|
haptics = true,
|
|
4075
4378
|
style,
|
|
4076
4379
|
disabled,
|
|
4077
|
-
hoverScale = 1.02
|
|
4078
|
-
...touchableProps
|
|
4380
|
+
hoverScale: _hoverScale = 1.02
|
|
4079
4381
|
}) {
|
|
4080
|
-
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
4081
|
-
pressScale,
|
|
4082
|
-
hoverScale,
|
|
4083
|
-
pressInSpring: SPRINGS.surfacePressIn,
|
|
4084
|
-
pressOutSpring: SPRINGS.surfacePressOut,
|
|
4085
|
-
disabled
|
|
4086
|
-
});
|
|
4087
4382
|
const handlePress = () => {
|
|
4088
4383
|
if (disabled || !onPress) return;
|
|
4089
4384
|
if (haptics) impactLight();
|
|
4090
4385
|
onPress();
|
|
4091
4386
|
};
|
|
4092
|
-
return /* @__PURE__ */
|
|
4093
|
-
|
|
4387
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4388
|
+
PressableCard,
|
|
4094
4389
|
{
|
|
4095
|
-
style
|
|
4096
|
-
|
|
4390
|
+
style,
|
|
4391
|
+
onPress: handlePress,
|
|
4392
|
+
enabled: !disabled,
|
|
4393
|
+
rippleColor: "transparent",
|
|
4394
|
+
touchSoundDisabled: true,
|
|
4395
|
+
activateOnHover: true,
|
|
4396
|
+
accessibilityRole: "button",
|
|
4397
|
+
accessibilityState: { disabled: !!disabled }
|
|
4097
4398
|
},
|
|
4098
|
-
|
|
4099
|
-
reactNative.TouchableOpacity,
|
|
4100
|
-
{
|
|
4101
|
-
onPress: handlePress,
|
|
4102
|
-
onPressIn,
|
|
4103
|
-
onPressOut,
|
|
4104
|
-
activeOpacity: 1,
|
|
4105
|
-
disabled,
|
|
4106
|
-
touchSoundDisabled: true,
|
|
4107
|
-
accessibilityRole: "button",
|
|
4108
|
-
accessibilityState: { disabled: !!disabled },
|
|
4109
|
-
...touchableProps
|
|
4110
|
-
},
|
|
4111
|
-
children
|
|
4112
|
-
)
|
|
4399
|
+
children
|
|
4113
4400
|
);
|
|
4114
4401
|
}
|
|
4115
4402
|
var weightMap = {
|
|
@@ -4144,23 +4431,23 @@ function DetailRowBase({
|
|
|
4144
4431
|
borderColor: "rgba(128,128,128,0.3)",
|
|
4145
4432
|
marginHorizontal: s(4)
|
|
4146
4433
|
};
|
|
4147
|
-
return /* @__PURE__ */
|
|
4434
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles35.row, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.labelSide }, resolvedLeftIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.icon }, resolvedLeftIcon) : null, typeof label === "string" ? /* @__PURE__ */ React25__default.default.createElement(
|
|
4148
4435
|
reactNative.Text,
|
|
4149
4436
|
{
|
|
4150
4437
|
style: [styles35.labelText, { color: colors.foregroundMuted, fontFamily: weightMap[labelWeight] }, labelStyle],
|
|
4151
4438
|
allowFontScaling: true
|
|
4152
4439
|
},
|
|
4153
4440
|
label
|
|
4154
|
-
) : label), separatorStyle ? /* @__PURE__ */
|
|
4441
|
+
) : label), separatorStyle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: separatorStyle }) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.spacer }), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.valueSide }, typeof value === "string" ? /* @__PURE__ */ React25__default.default.createElement(
|
|
4155
4442
|
reactNative.Text,
|
|
4156
4443
|
{
|
|
4157
4444
|
style: [styles35.valueText, { color: valueColor ?? colors.foreground }, valueStyle],
|
|
4158
4445
|
allowFontScaling: true
|
|
4159
4446
|
},
|
|
4160
4447
|
value
|
|
4161
|
-
) : value, resolvedRightIcon ? /* @__PURE__ */
|
|
4448
|
+
) : value, resolvedRightIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.icon }, resolvedRightIcon) : null));
|
|
4162
4449
|
}
|
|
4163
|
-
var DetailRow =
|
|
4450
|
+
var DetailRow = React25__default.default.memo(DetailRowBase);
|
|
4164
4451
|
var styles35 = reactNative.StyleSheet.create({
|
|
4165
4452
|
row: {
|
|
4166
4453
|
flexDirection: "row",
|
|
@@ -4197,7 +4484,7 @@ var styles35 = reactNative.StyleSheet.create({
|
|
|
4197
4484
|
}
|
|
4198
4485
|
});
|
|
4199
4486
|
function Form({ children, style }) {
|
|
4200
|
-
return /* @__PURE__ */
|
|
4487
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.form, style] }, children);
|
|
4201
4488
|
}
|
|
4202
4489
|
function FormField({
|
|
4203
4490
|
children,
|
|
@@ -4209,14 +4496,14 @@ function FormField({
|
|
|
4209
4496
|
errorStyle
|
|
4210
4497
|
}) {
|
|
4211
4498
|
const { colors } = useTheme();
|
|
4212
|
-
return /* @__PURE__ */
|
|
4499
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.field, style] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.label, { color: colors.foreground }, labelStyle], allowFontScaling: true }, label, required ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: { color: colors.destructive } }, " *") : null) : null, children, error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.error, { color: colors.destructive }, errorStyle], allowFontScaling: true }, error) : null);
|
|
4213
4500
|
}
|
|
4214
4501
|
function FormSection({ children, title, description, style }) {
|
|
4215
4502
|
const { colors } = useTheme();
|
|
4216
|
-
return /* @__PURE__ */
|
|
4503
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.section, style] }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles36.sectionHeader }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.sectionTitle, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.sectionDescription, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null) : null, children);
|
|
4217
4504
|
}
|
|
4218
4505
|
function FormFooter({ children, style }) {
|
|
4219
|
-
return /* @__PURE__ */
|
|
4506
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.footer, style] }, children);
|
|
4220
4507
|
}
|
|
4221
4508
|
Form.Field = FormField;
|
|
4222
4509
|
Form.Section = FormSection;
|
|
@@ -4265,7 +4552,7 @@ var defaultKeyExtractor = (item, index) => {
|
|
|
4265
4552
|
return id !== void 0 ? String(id) : String(index);
|
|
4266
4553
|
};
|
|
4267
4554
|
function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, ref) {
|
|
4268
|
-
const getItemLayout =
|
|
4555
|
+
const getItemLayout = React25.useCallback(
|
|
4269
4556
|
(_data, index) => ({
|
|
4270
4557
|
length: itemHeight ?? 0,
|
|
4271
4558
|
offset: (itemHeight ?? 0) * index,
|
|
@@ -4273,7 +4560,7 @@ function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, re
|
|
|
4273
4560
|
}),
|
|
4274
4561
|
[itemHeight]
|
|
4275
4562
|
);
|
|
4276
|
-
return /* @__PURE__ */
|
|
4563
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4277
4564
|
reactNative.FlatList,
|
|
4278
4565
|
{
|
|
4279
4566
|
ref,
|
|
@@ -4285,7 +4572,899 @@ function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, re
|
|
|
4285
4572
|
}
|
|
4286
4573
|
);
|
|
4287
4574
|
}
|
|
4288
|
-
var VirtualList =
|
|
4575
|
+
var VirtualList = React25__default.default.forwardRef(VirtualListInner);
|
|
4576
|
+
function RetrayProvider({ children, theme, colorScheme = "system" }) {
|
|
4577
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNativeSafeAreaContext.SafeAreaProvider, { initialMetrics: reactNativeSafeAreaContext.initialWindowMetrics }, /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles37.root }, /* @__PURE__ */ React25__default.default.createElement(ThemeProvider, { theme, colorScheme }, /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetModalProvider, null, /* @__PURE__ */ React25__default.default.createElement(ToastProvider, null, children)))));
|
|
4578
|
+
}
|
|
4579
|
+
var styles37 = reactNative.StyleSheet.create({
|
|
4580
|
+
root: { flex: 1 }
|
|
4581
|
+
});
|
|
4582
|
+
function DefaultErrorFallback({
|
|
4583
|
+
error,
|
|
4584
|
+
reset,
|
|
4585
|
+
title = "Something went wrong",
|
|
4586
|
+
message
|
|
4587
|
+
}) {
|
|
4588
|
+
const { colors } = useTheme();
|
|
4589
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles38.container, { backgroundColor: colors.background }], accessibilityRole: "alert" }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles38.iconCircle, { backgroundColor: colors.destructiveTint }] }, renderIcon("alert-triangle", ms(28), colors.destructive)), /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles38.title, { color: colors.foreground }], allowFontScaling: true }, title), /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles38.message, { color: colors.foregroundMuted }], allowFontScaling: true }, message ?? error.message ?? "An unexpected error occurred."), /* @__PURE__ */ React25__default.default.createElement(
|
|
4590
|
+
reactNative.TouchableOpacity,
|
|
4591
|
+
{
|
|
4592
|
+
style: [styles38.button, { backgroundColor: colors.primary }],
|
|
4593
|
+
onPress: () => {
|
|
4594
|
+
impactLight();
|
|
4595
|
+
reset();
|
|
4596
|
+
},
|
|
4597
|
+
activeOpacity: 0.85,
|
|
4598
|
+
touchSoundDisabled: true,
|
|
4599
|
+
accessibilityRole: "button",
|
|
4600
|
+
accessibilityLabel: "Try again"
|
|
4601
|
+
},
|
|
4602
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles38.buttonLabel, { color: colors.primaryForeground }], allowFontScaling: true }, "Try again")
|
|
4603
|
+
));
|
|
4604
|
+
}
|
|
4605
|
+
var ErrorBoundary = class extends React25__default.default.Component {
|
|
4606
|
+
constructor() {
|
|
4607
|
+
super(...arguments);
|
|
4608
|
+
this.state = { error: null };
|
|
4609
|
+
this.reset = () => {
|
|
4610
|
+
this.setState({ error: null });
|
|
4611
|
+
};
|
|
4612
|
+
}
|
|
4613
|
+
static getDerivedStateFromError(error) {
|
|
4614
|
+
return { error };
|
|
4615
|
+
}
|
|
4616
|
+
componentDidCatch(error, info) {
|
|
4617
|
+
this.props.onError?.(error, info);
|
|
4618
|
+
}
|
|
4619
|
+
render() {
|
|
4620
|
+
const { error } = this.state;
|
|
4621
|
+
if (error) {
|
|
4622
|
+
const { fallback, title, message } = this.props;
|
|
4623
|
+
if (typeof fallback === "function") {
|
|
4624
|
+
return fallback({ error, reset: this.reset });
|
|
4625
|
+
}
|
|
4626
|
+
if (fallback !== void 0) {
|
|
4627
|
+
return fallback;
|
|
4628
|
+
}
|
|
4629
|
+
return /* @__PURE__ */ React25__default.default.createElement(DefaultErrorFallback, { error, reset: this.reset, title, message });
|
|
4630
|
+
}
|
|
4631
|
+
return this.props.children;
|
|
4632
|
+
}
|
|
4633
|
+
};
|
|
4634
|
+
var styles38 = reactNative.StyleSheet.create({
|
|
4635
|
+
container: {
|
|
4636
|
+
flex: 1,
|
|
4637
|
+
alignItems: "center",
|
|
4638
|
+
justifyContent: "center",
|
|
4639
|
+
paddingHorizontal: s(32),
|
|
4640
|
+
gap: vs(12)
|
|
4641
|
+
},
|
|
4642
|
+
iconCircle: {
|
|
4643
|
+
width: s(64),
|
|
4644
|
+
height: s(64),
|
|
4645
|
+
borderRadius: RADIUS.full,
|
|
4646
|
+
alignItems: "center",
|
|
4647
|
+
justifyContent: "center",
|
|
4648
|
+
marginBottom: vs(4)
|
|
4649
|
+
},
|
|
4650
|
+
title: {
|
|
4651
|
+
fontFamily: "Sohne-SemiBold",
|
|
4652
|
+
fontSize: ms(18),
|
|
4653
|
+
lineHeight: mvs(24),
|
|
4654
|
+
textAlign: "center"
|
|
4655
|
+
},
|
|
4656
|
+
message: {
|
|
4657
|
+
fontFamily: "Sohne-Regular",
|
|
4658
|
+
fontSize: ms(14),
|
|
4659
|
+
lineHeight: mvs(20),
|
|
4660
|
+
textAlign: "center"
|
|
4661
|
+
},
|
|
4662
|
+
button: {
|
|
4663
|
+
marginTop: vs(8),
|
|
4664
|
+
paddingHorizontal: s(20),
|
|
4665
|
+
paddingVertical: vs(10),
|
|
4666
|
+
borderRadius: RADIUS.md,
|
|
4667
|
+
minHeight: vs(44),
|
|
4668
|
+
alignItems: "center",
|
|
4669
|
+
justifyContent: "center"
|
|
4670
|
+
},
|
|
4671
|
+
buttonLabel: {
|
|
4672
|
+
fontFamily: "Sohne-Medium",
|
|
4673
|
+
fontSize: ms(15)
|
|
4674
|
+
}
|
|
4675
|
+
});
|
|
4676
|
+
function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }) {
|
|
4677
|
+
const progress = Animated13.useSharedValue(active ? 1 : 0);
|
|
4678
|
+
React25.useEffect(() => {
|
|
4679
|
+
progress.value = Animated13.withSpring(active ? 1 : 0, SPRINGS.glide);
|
|
4680
|
+
}, [active, progress]);
|
|
4681
|
+
const animatedStyle = Animated13.useAnimatedStyle(() => ({
|
|
4682
|
+
width: size + progress.value * size * 1.5,
|
|
4683
|
+
backgroundColor: Animated13.interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor])
|
|
4684
|
+
}));
|
|
4685
|
+
const dot = /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [{ height: size, borderRadius: size / 2 }, animatedStyle] });
|
|
4686
|
+
if (!onPress) return dot;
|
|
4687
|
+
const handlePress = () => {
|
|
4688
|
+
selectionAsync();
|
|
4689
|
+
onPress();
|
|
4690
|
+
};
|
|
4691
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4692
|
+
reactNative.TouchableOpacity,
|
|
4693
|
+
{
|
|
4694
|
+
onPress: handlePress,
|
|
4695
|
+
activeOpacity: 0.7,
|
|
4696
|
+
touchSoundDisabled: true,
|
|
4697
|
+
accessibilityRole: "button",
|
|
4698
|
+
accessibilityLabel: `Page ${index + 1} of ${total}${active ? ", current page" : ""}`,
|
|
4699
|
+
hitSlop: { top: 8, bottom: 8, left: 4, right: 4 }
|
|
4700
|
+
},
|
|
4701
|
+
dot
|
|
4702
|
+
);
|
|
4703
|
+
}
|
|
4704
|
+
function PagerDots({
|
|
4705
|
+
count,
|
|
4706
|
+
activeIndex,
|
|
4707
|
+
onDotPress,
|
|
4708
|
+
showControls = false,
|
|
4709
|
+
dotSize = 8,
|
|
4710
|
+
spacing = 8,
|
|
4711
|
+
activeColor,
|
|
4712
|
+
inactiveColor,
|
|
4713
|
+
style
|
|
4714
|
+
}) {
|
|
4715
|
+
const { colors } = useTheme();
|
|
4716
|
+
const resolvedActive = activeColor ?? colors.primary;
|
|
4717
|
+
const resolvedInactive = inactiveColor ?? colors.border;
|
|
4718
|
+
const size = s(dotSize);
|
|
4719
|
+
const hasControls = showControls !== false;
|
|
4720
|
+
const canGoPrev = activeIndex > 0;
|
|
4721
|
+
const canGoNext = activeIndex < count - 1;
|
|
4722
|
+
const handlePrevious = () => {
|
|
4723
|
+
if (!canGoPrev) return;
|
|
4724
|
+
selectionAsync();
|
|
4725
|
+
if (typeof showControls === "object" && showControls.onPrevious) {
|
|
4726
|
+
showControls.onPrevious();
|
|
4727
|
+
} else if (onDotPress) {
|
|
4728
|
+
onDotPress(activeIndex - 1);
|
|
4729
|
+
}
|
|
4730
|
+
};
|
|
4731
|
+
const handleNext = () => {
|
|
4732
|
+
if (!canGoNext) return;
|
|
4733
|
+
selectionAsync();
|
|
4734
|
+
if (typeof showControls === "object" && showControls.onNext) {
|
|
4735
|
+
showControls.onNext();
|
|
4736
|
+
} else if (onDotPress) {
|
|
4737
|
+
onDotPress(activeIndex + 1);
|
|
4738
|
+
}
|
|
4739
|
+
};
|
|
4740
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4741
|
+
reactNative.View,
|
|
4742
|
+
{
|
|
4743
|
+
style: [styles39.container, { gap: s(spacing) }, style],
|
|
4744
|
+
accessibilityRole: "adjustable",
|
|
4745
|
+
accessibilityLabel: `Page ${activeIndex + 1} of ${count}`
|
|
4746
|
+
},
|
|
4747
|
+
hasControls && /* @__PURE__ */ React25__default.default.createElement(
|
|
4748
|
+
reactNative.TouchableOpacity,
|
|
4749
|
+
{
|
|
4750
|
+
onPress: handlePrevious,
|
|
4751
|
+
disabled: !canGoPrev,
|
|
4752
|
+
activeOpacity: 0.7,
|
|
4753
|
+
touchSoundDisabled: true,
|
|
4754
|
+
accessibilityRole: "button",
|
|
4755
|
+
accessibilityLabel: "Previous page",
|
|
4756
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
4757
|
+
style: [styles39.controlBtn, !canGoPrev && styles39.controlBtnDisabled]
|
|
4758
|
+
},
|
|
4759
|
+
renderIcon("chevron-left", s(18), canGoPrev ? colors.foreground : colors.foregroundMuted)
|
|
4760
|
+
),
|
|
4761
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles39.dotsRow, { gap: s(spacing) }] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React25__default.default.createElement(
|
|
4762
|
+
Dot,
|
|
4763
|
+
{
|
|
4764
|
+
key: i,
|
|
4765
|
+
active: i === activeIndex,
|
|
4766
|
+
size,
|
|
4767
|
+
activeColor: resolvedActive,
|
|
4768
|
+
inactiveColor: resolvedInactive,
|
|
4769
|
+
index: i,
|
|
4770
|
+
total: count,
|
|
4771
|
+
onPress: onDotPress ? () => onDotPress(i) : void 0
|
|
4772
|
+
}
|
|
4773
|
+
))),
|
|
4774
|
+
hasControls && /* @__PURE__ */ React25__default.default.createElement(
|
|
4775
|
+
reactNative.TouchableOpacity,
|
|
4776
|
+
{
|
|
4777
|
+
onPress: handleNext,
|
|
4778
|
+
disabled: !canGoNext,
|
|
4779
|
+
activeOpacity: 0.7,
|
|
4780
|
+
touchSoundDisabled: true,
|
|
4781
|
+
accessibilityRole: "button",
|
|
4782
|
+
accessibilityLabel: "Next page",
|
|
4783
|
+
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
4784
|
+
style: [styles39.controlBtn, !canGoNext && styles39.controlBtnDisabled]
|
|
4785
|
+
},
|
|
4786
|
+
renderIcon("chevron-right", s(18), canGoNext ? colors.foreground : colors.foregroundMuted)
|
|
4787
|
+
)
|
|
4788
|
+
);
|
|
4789
|
+
}
|
|
4790
|
+
var styles39 = reactNative.StyleSheet.create({
|
|
4791
|
+
container: {
|
|
4792
|
+
flexDirection: "row",
|
|
4793
|
+
alignItems: "center",
|
|
4794
|
+
justifyContent: "center"
|
|
4795
|
+
},
|
|
4796
|
+
dotsRow: {
|
|
4797
|
+
flexDirection: "row",
|
|
4798
|
+
alignItems: "center"
|
|
4799
|
+
},
|
|
4800
|
+
controlBtn: {
|
|
4801
|
+
padding: s(4)
|
|
4802
|
+
},
|
|
4803
|
+
controlBtnDisabled: {
|
|
4804
|
+
opacity: 0.3
|
|
4805
|
+
}
|
|
4806
|
+
});
|
|
4807
|
+
function AppHeader({
|
|
4808
|
+
title,
|
|
4809
|
+
subtitle,
|
|
4810
|
+
onBack,
|
|
4811
|
+
backIconName = "chevron-left",
|
|
4812
|
+
left,
|
|
4813
|
+
right,
|
|
4814
|
+
titleAlign = "auto",
|
|
4815
|
+
bordered = true,
|
|
4816
|
+
withSafeArea = true,
|
|
4817
|
+
backgroundColor,
|
|
4818
|
+
style
|
|
4819
|
+
}) {
|
|
4820
|
+
const { colors } = useTheme();
|
|
4821
|
+
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
4822
|
+
const { width } = reactNative.useWindowDimensions();
|
|
4823
|
+
const isWide = width >= BREAKPOINTS.wide;
|
|
4824
|
+
const centered = titleAlign === "center" || titleAlign === "auto" && isWide;
|
|
4825
|
+
const leftNode = left ?? (onBack ? /* @__PURE__ */ React25__default.default.createElement(
|
|
4826
|
+
IconButton,
|
|
4827
|
+
{
|
|
4828
|
+
iconName: backIconName,
|
|
4829
|
+
variant: "text",
|
|
4830
|
+
size: "md",
|
|
4831
|
+
onPress: onBack,
|
|
4832
|
+
accessibilityLabel: "Go back"
|
|
4833
|
+
}
|
|
4834
|
+
) : null);
|
|
4835
|
+
const titleBlock = /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles40.titleBlock, centered && styles40.titleBlockCentered], pointerEvents: "none" }, title ? /* @__PURE__ */ React25__default.default.createElement(
|
|
4836
|
+
reactNative.Text,
|
|
4837
|
+
{
|
|
4838
|
+
style: [styles40.title, { color: colors.foreground }, centered && styles40.textCentered],
|
|
4839
|
+
numberOfLines: 1,
|
|
4840
|
+
allowFontScaling: true,
|
|
4841
|
+
accessibilityRole: "header"
|
|
4842
|
+
},
|
|
4843
|
+
title
|
|
4844
|
+
) : null, subtitle ? /* @__PURE__ */ React25__default.default.createElement(
|
|
4845
|
+
reactNative.Text,
|
|
4846
|
+
{
|
|
4847
|
+
style: [styles40.subtitle, { color: colors.foregroundMuted }, centered && styles40.textCentered],
|
|
4848
|
+
numberOfLines: 1,
|
|
4849
|
+
allowFontScaling: true
|
|
4850
|
+
},
|
|
4851
|
+
subtitle
|
|
4852
|
+
) : null);
|
|
4853
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4854
|
+
reactNative.View,
|
|
4855
|
+
{
|
|
4856
|
+
style: [
|
|
4857
|
+
styles40.container,
|
|
4858
|
+
{
|
|
4859
|
+
backgroundColor: backgroundColor ?? colors.background,
|
|
4860
|
+
paddingTop: withSafeArea ? insets.top : 0,
|
|
4861
|
+
borderBottomWidth: bordered ? reactNative.StyleSheet.hairlineWidth : 0,
|
|
4862
|
+
borderBottomColor: colors.border
|
|
4863
|
+
},
|
|
4864
|
+
style
|
|
4865
|
+
]
|
|
4866
|
+
},
|
|
4867
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles40.bar }, centered ? /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, titleBlock), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles40.side }, leftNode), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles40.side, styles40.sideRight] }, right)) : /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles40.side }, leftNode), titleBlock, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles40.side, styles40.sideRight] }, right)))
|
|
4868
|
+
);
|
|
4869
|
+
}
|
|
4870
|
+
var styles40 = reactNative.StyleSheet.create({
|
|
4871
|
+
container: {
|
|
4872
|
+
width: "100%"
|
|
4873
|
+
},
|
|
4874
|
+
bar: {
|
|
4875
|
+
minHeight: vs(48),
|
|
4876
|
+
flexDirection: "row",
|
|
4877
|
+
alignItems: "center",
|
|
4878
|
+
paddingHorizontal: s(8)
|
|
4879
|
+
},
|
|
4880
|
+
side: {
|
|
4881
|
+
minWidth: s(44),
|
|
4882
|
+
flexDirection: "row",
|
|
4883
|
+
alignItems: "center",
|
|
4884
|
+
justifyContent: "flex-start"
|
|
4885
|
+
},
|
|
4886
|
+
sideRight: {
|
|
4887
|
+
justifyContent: "flex-end"
|
|
4888
|
+
},
|
|
4889
|
+
titleBlock: {
|
|
4890
|
+
flex: 1,
|
|
4891
|
+
justifyContent: "center",
|
|
4892
|
+
paddingHorizontal: s(8),
|
|
4893
|
+
gap: vs(1)
|
|
4894
|
+
},
|
|
4895
|
+
titleBlockCentered: {
|
|
4896
|
+
alignItems: "center"
|
|
4897
|
+
},
|
|
4898
|
+
title: {
|
|
4899
|
+
fontFamily: "Sohne-SemiBold",
|
|
4900
|
+
fontSize: ms(18),
|
|
4901
|
+
lineHeight: mvs(24)
|
|
4902
|
+
},
|
|
4903
|
+
subtitle: {
|
|
4904
|
+
fontFamily: "Sohne-Regular",
|
|
4905
|
+
fontSize: ms(13),
|
|
4906
|
+
lineHeight: mvs(16)
|
|
4907
|
+
},
|
|
4908
|
+
textCentered: {
|
|
4909
|
+
textAlign: "center"
|
|
4910
|
+
}
|
|
4911
|
+
});
|
|
4912
|
+
function isSelected(value, candidate) {
|
|
4913
|
+
if (value == null) return false;
|
|
4914
|
+
return Array.isArray(value) ? value.includes(candidate) : value === candidate;
|
|
4915
|
+
}
|
|
4916
|
+
function Cell({ item, selected, width, onPress }) {
|
|
4917
|
+
const { colors } = useTheme();
|
|
4918
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
4919
|
+
pressScale: PRESS_SCALE.chip,
|
|
4920
|
+
disabled: item.disabled
|
|
4921
|
+
});
|
|
4922
|
+
const iconColor = selected ? colors.primary : colors.foregroundSubtle;
|
|
4923
|
+
const iconNode = item.icon ?? (item.iconName ? renderIcon(item.iconName, ms(24), iconColor) : null);
|
|
4924
|
+
return /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [{ width }, animatedStyle] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
4925
|
+
reactNative.TouchableOpacity,
|
|
4926
|
+
{
|
|
4927
|
+
onPress,
|
|
4928
|
+
onPressIn,
|
|
4929
|
+
onPressOut,
|
|
4930
|
+
disabled: item.disabled,
|
|
4931
|
+
activeOpacity: 1,
|
|
4932
|
+
touchSoundDisabled: true,
|
|
4933
|
+
accessibilityRole: "button",
|
|
4934
|
+
accessibilityState: { selected, disabled: item.disabled },
|
|
4935
|
+
accessibilityLabel: item.label ?? String(item.value),
|
|
4936
|
+
...hoverHandlers,
|
|
4937
|
+
style: [
|
|
4938
|
+
styles41.cell,
|
|
4939
|
+
{
|
|
4940
|
+
backgroundColor: selected ? colors.primary + "14" : colors.surface,
|
|
4941
|
+
borderColor: selected ? colors.primary : "transparent"
|
|
4942
|
+
},
|
|
4943
|
+
item.disabled && styles41.cellDisabled
|
|
4944
|
+
]
|
|
4945
|
+
},
|
|
4946
|
+
iconNode,
|
|
4947
|
+
item.label ? /* @__PURE__ */ React25__default.default.createElement(
|
|
4948
|
+
reactNative.Text,
|
|
4949
|
+
{
|
|
4950
|
+
style: [styles41.label, { color: selected ? colors.primary : colors.foreground }],
|
|
4951
|
+
numberOfLines: 1,
|
|
4952
|
+
allowFontScaling: true
|
|
4953
|
+
},
|
|
4954
|
+
item.label
|
|
4955
|
+
) : null
|
|
4956
|
+
));
|
|
4957
|
+
}
|
|
4958
|
+
function SelectableGrid({
|
|
4959
|
+
items,
|
|
4960
|
+
value,
|
|
4961
|
+
onChange,
|
|
4962
|
+
multiple = false,
|
|
4963
|
+
numColumns = 4,
|
|
4964
|
+
gap = 12,
|
|
4965
|
+
orientation = "grid",
|
|
4966
|
+
style
|
|
4967
|
+
}) {
|
|
4968
|
+
const [containerWidth, setContainerWidth] = React25.useState(0);
|
|
4969
|
+
const gapPx = s(gap);
|
|
4970
|
+
const cellWidth = containerWidth > 0 ? (containerWidth - gapPx * (numColumns - 1)) / numColumns - 0.5 : 0;
|
|
4971
|
+
const horizCellWidth = s(72);
|
|
4972
|
+
const handlePress = (item) => {
|
|
4973
|
+
if (item.disabled) return;
|
|
4974
|
+
selectionAsync();
|
|
4975
|
+
onChange(item.value);
|
|
4976
|
+
};
|
|
4977
|
+
if (orientation === "horizontal") {
|
|
4978
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4979
|
+
reactNative.ScrollView,
|
|
4980
|
+
{
|
|
4981
|
+
horizontal: true,
|
|
4982
|
+
showsHorizontalScrollIndicator: false,
|
|
4983
|
+
contentContainerStyle: [styles41.horizontal, { gap: gapPx }, style],
|
|
4984
|
+
accessibilityRole: multiple ? void 0 : "radiogroup"
|
|
4985
|
+
},
|
|
4986
|
+
items.map((item) => /* @__PURE__ */ React25__default.default.createElement(
|
|
4987
|
+
Cell,
|
|
4988
|
+
{
|
|
4989
|
+
key: String(item.value),
|
|
4990
|
+
item,
|
|
4991
|
+
selected: isSelected(value, item.value),
|
|
4992
|
+
width: horizCellWidth,
|
|
4993
|
+
onPress: () => handlePress(item)
|
|
4994
|
+
}
|
|
4995
|
+
))
|
|
4996
|
+
);
|
|
4997
|
+
}
|
|
4998
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
4999
|
+
reactNative.View,
|
|
5000
|
+
{
|
|
5001
|
+
style: [styles41.grid, { gap: gapPx }, style],
|
|
5002
|
+
onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width),
|
|
5003
|
+
accessibilityRole: multiple ? void 0 : "radiogroup"
|
|
5004
|
+
},
|
|
5005
|
+
cellWidth > 0 ? items.map((item) => /* @__PURE__ */ React25__default.default.createElement(
|
|
5006
|
+
Cell,
|
|
5007
|
+
{
|
|
5008
|
+
key: String(item.value),
|
|
5009
|
+
item,
|
|
5010
|
+
selected: isSelected(value, item.value),
|
|
5011
|
+
width: cellWidth,
|
|
5012
|
+
onPress: () => handlePress(item)
|
|
5013
|
+
}
|
|
5014
|
+
)) : null
|
|
5015
|
+
);
|
|
5016
|
+
}
|
|
5017
|
+
var styles41 = reactNative.StyleSheet.create({
|
|
5018
|
+
grid: {
|
|
5019
|
+
flexDirection: "row",
|
|
5020
|
+
flexWrap: "wrap"
|
|
5021
|
+
},
|
|
5022
|
+
horizontal: {
|
|
5023
|
+
flexDirection: "row",
|
|
5024
|
+
paddingHorizontal: s(4)
|
|
5025
|
+
},
|
|
5026
|
+
cell: {
|
|
5027
|
+
flex: 1,
|
|
5028
|
+
borderRadius: RADIUS.md,
|
|
5029
|
+
borderWidth: 2,
|
|
5030
|
+
alignItems: "center",
|
|
5031
|
+
justifyContent: "center",
|
|
5032
|
+
gap: vs(4),
|
|
5033
|
+
paddingHorizontal: s(12),
|
|
5034
|
+
paddingVertical: vs(12)
|
|
5035
|
+
},
|
|
5036
|
+
cellDisabled: {
|
|
5037
|
+
opacity: 0.4
|
|
5038
|
+
},
|
|
5039
|
+
label: {
|
|
5040
|
+
fontFamily: "Sohne-Medium",
|
|
5041
|
+
fontSize: ms(12),
|
|
5042
|
+
lineHeight: mvs(15),
|
|
5043
|
+
textAlign: "center"
|
|
5044
|
+
}
|
|
5045
|
+
});
|
|
5046
|
+
var normalize = (f) => typeof f === "string" ? { label: f, included: true } : { included: true, ...f };
|
|
5047
|
+
function PricingCard({
|
|
5048
|
+
name,
|
|
5049
|
+
price,
|
|
5050
|
+
period,
|
|
5051
|
+
description,
|
|
5052
|
+
features = [],
|
|
5053
|
+
ctaLabel,
|
|
5054
|
+
onCtaPress,
|
|
5055
|
+
badge,
|
|
5056
|
+
highlighted = false,
|
|
5057
|
+
footnote,
|
|
5058
|
+
style
|
|
5059
|
+
}) {
|
|
5060
|
+
const { colors } = useTheme();
|
|
5061
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
5062
|
+
reactNative.View,
|
|
5063
|
+
{
|
|
5064
|
+
style: [
|
|
5065
|
+
styles42.card,
|
|
5066
|
+
{
|
|
5067
|
+
backgroundColor: colors.card,
|
|
5068
|
+
borderColor: highlighted ? colors.primary : colors.border,
|
|
5069
|
+
borderWidth: highlighted ? 2 : reactNative.StyleSheet.hairlineWidth
|
|
5070
|
+
},
|
|
5071
|
+
highlighted && SHADOWS.md,
|
|
5072
|
+
style
|
|
5073
|
+
],
|
|
5074
|
+
accessibilityRole: "summary"
|
|
5075
|
+
},
|
|
5076
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles42.header }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.name, { color: colors.foreground }], allowFontScaling: true }, name), badge ? /* @__PURE__ */ React25__default.default.createElement(Badge, { label: badge, variant: highlighted ? "default" : "secondary", size: "sm" }) : null),
|
|
5077
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles42.priceRow }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.price, { color: colors.foreground }], allowFontScaling: true }, price), period ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.period, { color: colors.foregroundMuted }], allowFontScaling: true }, period) : null),
|
|
5078
|
+
description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null,
|
|
5079
|
+
features.length > 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles42.features }, features.map(normalize).map((f, i) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: i, style: styles42.featureRow }, renderIcon(
|
|
5080
|
+
f.included ? "check" : "minus",
|
|
5081
|
+
ms(16),
|
|
5082
|
+
f.included ? colors.success : colors.foregroundMuted
|
|
5083
|
+
), /* @__PURE__ */ React25__default.default.createElement(
|
|
5084
|
+
reactNative.Text,
|
|
5085
|
+
{
|
|
5086
|
+
style: [
|
|
5087
|
+
styles42.featureLabel,
|
|
5088
|
+
{ color: f.included ? colors.foreground : colors.foregroundMuted },
|
|
5089
|
+
!f.included && styles42.featureExcluded
|
|
5090
|
+
],
|
|
5091
|
+
allowFontScaling: true
|
|
5092
|
+
},
|
|
5093
|
+
f.label
|
|
5094
|
+
)))) : null,
|
|
5095
|
+
ctaLabel ? /* @__PURE__ */ React25__default.default.createElement(
|
|
5096
|
+
Button,
|
|
5097
|
+
{
|
|
5098
|
+
label: ctaLabel,
|
|
5099
|
+
variant: highlighted ? "primary" : "secondary",
|
|
5100
|
+
fullWidth: true,
|
|
5101
|
+
onPress: onCtaPress,
|
|
5102
|
+
style: styles42.cta
|
|
5103
|
+
}
|
|
5104
|
+
) : null,
|
|
5105
|
+
footnote ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.footnote, { color: colors.foregroundMuted }], allowFontScaling: true }, footnote) : null
|
|
5106
|
+
);
|
|
5107
|
+
}
|
|
5108
|
+
var styles42 = reactNative.StyleSheet.create({
|
|
5109
|
+
card: {
|
|
5110
|
+
borderRadius: RADIUS.md,
|
|
5111
|
+
padding: s(16),
|
|
5112
|
+
gap: vs(8)
|
|
5113
|
+
},
|
|
5114
|
+
header: {
|
|
5115
|
+
flexDirection: "row",
|
|
5116
|
+
alignItems: "center",
|
|
5117
|
+
justifyContent: "space-between",
|
|
5118
|
+
gap: s(8)
|
|
5119
|
+
},
|
|
5120
|
+
name: {
|
|
5121
|
+
fontFamily: "Sohne-SemiBold",
|
|
5122
|
+
fontSize: ms(16),
|
|
5123
|
+
lineHeight: mvs(20)
|
|
5124
|
+
},
|
|
5125
|
+
priceRow: {
|
|
5126
|
+
flexDirection: "row",
|
|
5127
|
+
alignItems: "baseline",
|
|
5128
|
+
gap: s(3)
|
|
5129
|
+
},
|
|
5130
|
+
price: {
|
|
5131
|
+
fontFamily: "Sohne-Bold",
|
|
5132
|
+
fontSize: ms(28),
|
|
5133
|
+
lineHeight: mvs(32),
|
|
5134
|
+
letterSpacing: -0.5
|
|
5135
|
+
},
|
|
5136
|
+
period: {
|
|
5137
|
+
fontFamily: "Sohne-Regular",
|
|
5138
|
+
fontSize: ms(13),
|
|
5139
|
+
lineHeight: mvs(16)
|
|
5140
|
+
},
|
|
5141
|
+
description: {
|
|
5142
|
+
fontFamily: "Sohne-Regular",
|
|
5143
|
+
fontSize: ms(13),
|
|
5144
|
+
lineHeight: mvs(18)
|
|
5145
|
+
},
|
|
5146
|
+
features: {
|
|
5147
|
+
gap: vs(6),
|
|
5148
|
+
marginTop: vs(2)
|
|
5149
|
+
},
|
|
5150
|
+
featureRow: {
|
|
5151
|
+
flexDirection: "row",
|
|
5152
|
+
alignItems: "center",
|
|
5153
|
+
gap: s(6)
|
|
5154
|
+
},
|
|
5155
|
+
featureLabel: {
|
|
5156
|
+
flex: 1,
|
|
5157
|
+
fontFamily: "Sohne-Regular",
|
|
5158
|
+
fontSize: ms(13),
|
|
5159
|
+
lineHeight: mvs(18)
|
|
5160
|
+
},
|
|
5161
|
+
featureExcluded: {
|
|
5162
|
+
textDecorationLine: "line-through"
|
|
5163
|
+
},
|
|
5164
|
+
cta: {
|
|
5165
|
+
marginTop: vs(2)
|
|
5166
|
+
},
|
|
5167
|
+
footnote: {
|
|
5168
|
+
fontFamily: "Sohne-Regular",
|
|
5169
|
+
fontSize: ms(11),
|
|
5170
|
+
lineHeight: mvs(14),
|
|
5171
|
+
textAlign: "center"
|
|
5172
|
+
}
|
|
5173
|
+
});
|
|
5174
|
+
function TabBar({
|
|
5175
|
+
items,
|
|
5176
|
+
activeKey,
|
|
5177
|
+
onTabPress,
|
|
5178
|
+
activeColor,
|
|
5179
|
+
inactiveColor,
|
|
5180
|
+
withSafeArea = true,
|
|
5181
|
+
style
|
|
5182
|
+
}) {
|
|
5183
|
+
const { colors } = useTheme();
|
|
5184
|
+
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
5185
|
+
const resolvedActive = activeColor ?? colors.primary;
|
|
5186
|
+
const resolvedInactive = inactiveColor ?? colors.foregroundMuted;
|
|
5187
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
5188
|
+
reactNative.View,
|
|
5189
|
+
{
|
|
5190
|
+
style: [
|
|
5191
|
+
styles43.container,
|
|
5192
|
+
{
|
|
5193
|
+
backgroundColor: colors.card,
|
|
5194
|
+
borderTopColor: colors.border,
|
|
5195
|
+
paddingBottom: withSafeArea ? insets.bottom : 0
|
|
5196
|
+
},
|
|
5197
|
+
style
|
|
5198
|
+
],
|
|
5199
|
+
accessibilityRole: "tablist"
|
|
5200
|
+
},
|
|
5201
|
+
items.map((item) => {
|
|
5202
|
+
const active = item.key === activeKey;
|
|
5203
|
+
const tint = active ? resolvedActive : resolvedInactive;
|
|
5204
|
+
const iconNode = item.icon ?? (item.iconName ? renderIcon(item.iconName, ms(24), tint) : null);
|
|
5205
|
+
const showBadge = item.badge !== void 0 && item.badge !== false;
|
|
5206
|
+
const badgeCount = typeof item.badge === "number" ? item.badge : void 0;
|
|
5207
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
5208
|
+
reactNative.TouchableOpacity,
|
|
5209
|
+
{
|
|
5210
|
+
key: item.key,
|
|
5211
|
+
style: styles43.tab,
|
|
5212
|
+
onPress: () => {
|
|
5213
|
+
if (!active) selectionAsync();
|
|
5214
|
+
onTabPress(item.key);
|
|
5215
|
+
},
|
|
5216
|
+
activeOpacity: 0.7,
|
|
5217
|
+
touchSoundDisabled: true,
|
|
5218
|
+
accessibilityRole: "tab",
|
|
5219
|
+
accessibilityState: { selected: active },
|
|
5220
|
+
accessibilityLabel: item.label ?? item.key
|
|
5221
|
+
},
|
|
5222
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, null, iconNode, showBadge ? /* @__PURE__ */ React25__default.default.createElement(
|
|
5223
|
+
reactNative.View,
|
|
5224
|
+
{
|
|
5225
|
+
style: [
|
|
5226
|
+
styles43.badge,
|
|
5227
|
+
{ backgroundColor: colors.destructive, borderColor: colors.card },
|
|
5228
|
+
badgeCount === void 0 && styles43.badgeDot
|
|
5229
|
+
]
|
|
5230
|
+
},
|
|
5231
|
+
badgeCount !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles43.badgeText, { color: colors.destructiveForeground }], allowFontScaling: false }, badgeCount > 99 ? "99+" : badgeCount) : null
|
|
5232
|
+
) : null),
|
|
5233
|
+
item.label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles43.label, { color: tint }], numberOfLines: 1, allowFontScaling: true }, item.label) : null
|
|
5234
|
+
);
|
|
5235
|
+
})
|
|
5236
|
+
);
|
|
5237
|
+
}
|
|
5238
|
+
var styles43 = reactNative.StyleSheet.create({
|
|
5239
|
+
container: {
|
|
5240
|
+
flexDirection: "row",
|
|
5241
|
+
borderTopWidth: reactNative.StyleSheet.hairlineWidth
|
|
5242
|
+
},
|
|
5243
|
+
tab: {
|
|
5244
|
+
flex: 1,
|
|
5245
|
+
alignItems: "center",
|
|
5246
|
+
justifyContent: "center",
|
|
5247
|
+
paddingTop: vs(8),
|
|
5248
|
+
paddingBottom: vs(6),
|
|
5249
|
+
gap: vs(2),
|
|
5250
|
+
minHeight: vs(48)
|
|
5251
|
+
},
|
|
5252
|
+
label: {
|
|
5253
|
+
fontFamily: "Sohne-Medium",
|
|
5254
|
+
fontSize: ms(11),
|
|
5255
|
+
lineHeight: mvs(14)
|
|
5256
|
+
},
|
|
5257
|
+
badge: {
|
|
5258
|
+
position: "absolute",
|
|
5259
|
+
top: -vs(4),
|
|
5260
|
+
right: -s(10),
|
|
5261
|
+
minWidth: s(16),
|
|
5262
|
+
height: s(16),
|
|
5263
|
+
borderRadius: s(8),
|
|
5264
|
+
borderWidth: 1.5,
|
|
5265
|
+
alignItems: "center",
|
|
5266
|
+
justifyContent: "center",
|
|
5267
|
+
paddingHorizontal: s(3)
|
|
5268
|
+
},
|
|
5269
|
+
badgeDot: {
|
|
5270
|
+
minWidth: s(10),
|
|
5271
|
+
height: s(10),
|
|
5272
|
+
borderRadius: s(5),
|
|
5273
|
+
top: -vs(2),
|
|
5274
|
+
right: -s(6),
|
|
5275
|
+
paddingHorizontal: 0
|
|
5276
|
+
},
|
|
5277
|
+
badgeText: {
|
|
5278
|
+
fontFamily: "Sohne-SemiBold",
|
|
5279
|
+
fontSize: ms(9),
|
|
5280
|
+
lineHeight: ms(11)
|
|
5281
|
+
}
|
|
5282
|
+
});
|
|
5283
|
+
var MAX_SCALE = 3;
|
|
5284
|
+
var DOUBLE_TAP_SCALE = 2.5;
|
|
5285
|
+
function ZoomableImage({ source, width, height, onZoomChange }) {
|
|
5286
|
+
const scale2 = Animated13.useSharedValue(1);
|
|
5287
|
+
const savedScale = Animated13.useSharedValue(1);
|
|
5288
|
+
const translateX = Animated13.useSharedValue(0);
|
|
5289
|
+
const translateY = Animated13.useSharedValue(0);
|
|
5290
|
+
const savedX = Animated13.useSharedValue(0);
|
|
5291
|
+
const savedY = Animated13.useSharedValue(0);
|
|
5292
|
+
const reportZoom = React25.useCallback((zoomed) => onZoomChange(zoomed), [onZoomChange]);
|
|
5293
|
+
const reset = () => {
|
|
5294
|
+
"worklet";
|
|
5295
|
+
scale2.value = Animated13.withTiming(1);
|
|
5296
|
+
savedScale.value = 1;
|
|
5297
|
+
translateX.value = Animated13.withTiming(0);
|
|
5298
|
+
translateY.value = Animated13.withTiming(0);
|
|
5299
|
+
savedX.value = 0;
|
|
5300
|
+
savedY.value = 0;
|
|
5301
|
+
Animated13.runOnJS(reportZoom)(false);
|
|
5302
|
+
};
|
|
5303
|
+
const pinch = reactNativeGestureHandler.Gesture.Pinch().onUpdate((e) => {
|
|
5304
|
+
scale2.value = Math.max(1, Math.min(savedScale.value * e.scale, MAX_SCALE));
|
|
5305
|
+
}).onEnd(() => {
|
|
5306
|
+
savedScale.value = scale2.value;
|
|
5307
|
+
if (scale2.value <= 1) {
|
|
5308
|
+
reset();
|
|
5309
|
+
} else {
|
|
5310
|
+
Animated13.runOnJS(reportZoom)(true);
|
|
5311
|
+
}
|
|
5312
|
+
});
|
|
5313
|
+
const pan = reactNativeGestureHandler.Gesture.Pan().onUpdate((e) => {
|
|
5314
|
+
if (scale2.value <= 1) return;
|
|
5315
|
+
translateX.value = savedX.value + e.translationX;
|
|
5316
|
+
translateY.value = savedY.value + e.translationY;
|
|
5317
|
+
}).onEnd(() => {
|
|
5318
|
+
savedX.value = translateX.value;
|
|
5319
|
+
savedY.value = translateY.value;
|
|
5320
|
+
});
|
|
5321
|
+
const doubleTap = reactNativeGestureHandler.Gesture.Tap().numberOfTaps(2).onEnd(() => {
|
|
5322
|
+
if (scale2.value > 1) {
|
|
5323
|
+
reset();
|
|
5324
|
+
} else {
|
|
5325
|
+
scale2.value = Animated13.withTiming(DOUBLE_TAP_SCALE);
|
|
5326
|
+
savedScale.value = DOUBLE_TAP_SCALE;
|
|
5327
|
+
Animated13.runOnJS(reportZoom)(true);
|
|
5328
|
+
}
|
|
5329
|
+
});
|
|
5330
|
+
const composed = reactNativeGestureHandler.Gesture.Exclusive(doubleTap, reactNativeGestureHandler.Gesture.Simultaneous(pinch, pan));
|
|
5331
|
+
const animatedStyle = Animated13.useAnimatedStyle(() => ({
|
|
5332
|
+
transform: [
|
|
5333
|
+
{ translateX: translateX.value },
|
|
5334
|
+
{ translateY: translateY.value },
|
|
5335
|
+
{ scale: scale2.value }
|
|
5336
|
+
]
|
|
5337
|
+
}));
|
|
5338
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: composed }, /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [{ width, height }, styles44.imageWrap] }, /* @__PURE__ */ React25__default.default.createElement(
|
|
5339
|
+
Animated13__default.default.Image,
|
|
5340
|
+
{
|
|
5341
|
+
source,
|
|
5342
|
+
style: [{ width, height }, animatedStyle],
|
|
5343
|
+
resizeMode: "contain"
|
|
5344
|
+
}
|
|
5345
|
+
)));
|
|
5346
|
+
}
|
|
5347
|
+
function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
5348
|
+
const { width, height } = reactNative.useWindowDimensions();
|
|
5349
|
+
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
5350
|
+
const [index, setIndex] = React25.useState(initialIndex);
|
|
5351
|
+
const [pagingEnabled, setPagingEnabled] = React25.useState(true);
|
|
5352
|
+
const scrollRef = React25__default.default.useRef(null);
|
|
5353
|
+
React25__default.default.useEffect(() => {
|
|
5354
|
+
if (!visible) return;
|
|
5355
|
+
const handle = requestAnimationFrame(() => {
|
|
5356
|
+
setIndex(initialIndex);
|
|
5357
|
+
setPagingEnabled(true);
|
|
5358
|
+
scrollRef.current?.scrollTo({ x: initialIndex * width, animated: false });
|
|
5359
|
+
});
|
|
5360
|
+
return () => cancelAnimationFrame(handle);
|
|
5361
|
+
}, [visible, initialIndex, width]);
|
|
5362
|
+
const dragY = Animated13.useSharedValue(0);
|
|
5363
|
+
const DISMISS_THRESHOLD = height * 0.18;
|
|
5364
|
+
const closeViewer = React25.useCallback(() => onClose(), [onClose]);
|
|
5365
|
+
const swipeDown = reactNativeGestureHandler.Gesture.Pan().enabled(pagingEnabled).activeOffsetY(12).failOffsetX([-16, 16]).onUpdate((e) => {
|
|
5366
|
+
dragY.value = Math.max(0, e.translationY);
|
|
5367
|
+
}).onEnd((e) => {
|
|
5368
|
+
if (e.translationY > DISMISS_THRESHOLD || e.velocityY > 800) {
|
|
5369
|
+
Animated13.runOnJS(closeViewer)();
|
|
5370
|
+
} else {
|
|
5371
|
+
dragY.value = Animated13.withTiming(0);
|
|
5372
|
+
}
|
|
5373
|
+
});
|
|
5374
|
+
React25__default.default.useEffect(() => {
|
|
5375
|
+
if (visible) dragY.value = 0;
|
|
5376
|
+
}, [visible, dragY]);
|
|
5377
|
+
const dismissStyle = Animated13.useAnimatedStyle(() => ({
|
|
5378
|
+
transform: [{ translateY: dragY.value }]
|
|
5379
|
+
}));
|
|
5380
|
+
const backdropStyle = Animated13.useAnimatedStyle(() => ({
|
|
5381
|
+
opacity: 1 - Math.min(dragY.value / (height * 0.5), 0.85)
|
|
5382
|
+
}));
|
|
5383
|
+
const onMomentumEnd = (e) => {
|
|
5384
|
+
const page = Math.round(e.nativeEvent.contentOffset.x / width);
|
|
5385
|
+
setIndex(page);
|
|
5386
|
+
};
|
|
5387
|
+
const goTo = (page) => {
|
|
5388
|
+
scrollRef.current?.scrollTo({ x: page * width, animated: true });
|
|
5389
|
+
setIndex(page);
|
|
5390
|
+
};
|
|
5391
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.Modal, { visible, transparent: false, animationType: "fade", onRequestClose: onClose, statusBarTranslucent: true }, /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles44.root }, /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles44.backdrop, backdropStyle], pointerEvents: "none" }), /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles44.container, dismissStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: swipeDown }, /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: styles44.root }, /* @__PURE__ */ React25__default.default.createElement(
|
|
5392
|
+
reactNative.ScrollView,
|
|
5393
|
+
{
|
|
5394
|
+
ref: scrollRef,
|
|
5395
|
+
horizontal: true,
|
|
5396
|
+
pagingEnabled: true,
|
|
5397
|
+
scrollEnabled: pagingEnabled,
|
|
5398
|
+
showsHorizontalScrollIndicator: false,
|
|
5399
|
+
onMomentumScrollEnd: onMomentumEnd,
|
|
5400
|
+
bounces: false
|
|
5401
|
+
},
|
|
5402
|
+
images.map((source, i) => /* @__PURE__ */ React25__default.default.createElement(
|
|
5403
|
+
ZoomableImage,
|
|
5404
|
+
{
|
|
5405
|
+
key: i,
|
|
5406
|
+
source,
|
|
5407
|
+
width,
|
|
5408
|
+
height,
|
|
5409
|
+
onZoomChange: (zoomed) => setPagingEnabled(!zoomed)
|
|
5410
|
+
}
|
|
5411
|
+
))
|
|
5412
|
+
))), /* @__PURE__ */ React25__default.default.createElement(
|
|
5413
|
+
reactNative.TouchableOpacity,
|
|
5414
|
+
{
|
|
5415
|
+
style: [styles44.closeButton, { top: insets.top + vs(8) }],
|
|
5416
|
+
onPress: onClose,
|
|
5417
|
+
activeOpacity: 0.7,
|
|
5418
|
+
touchSoundDisabled: true,
|
|
5419
|
+
accessibilityRole: "button",
|
|
5420
|
+
accessibilityLabel: "Close",
|
|
5421
|
+
hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
|
|
5422
|
+
},
|
|
5423
|
+
renderIcon("x", 26, "#fff")
|
|
5424
|
+
), images.length > 1 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles44.dots, { bottom: insets.bottom + vs(16) }], pointerEvents: "box-none" }, /* @__PURE__ */ React25__default.default.createElement(
|
|
5425
|
+
PagerDots,
|
|
5426
|
+
{
|
|
5427
|
+
count: images.length,
|
|
5428
|
+
activeIndex: index,
|
|
5429
|
+
onDotPress: goTo,
|
|
5430
|
+
activeColor: "#fff",
|
|
5431
|
+
inactiveColor: "rgba(255,255,255,0.4)"
|
|
5432
|
+
}
|
|
5433
|
+
)) : null)));
|
|
5434
|
+
}
|
|
5435
|
+
var styles44 = reactNative.StyleSheet.create({
|
|
5436
|
+
root: {
|
|
5437
|
+
flex: 1
|
|
5438
|
+
},
|
|
5439
|
+
container: {
|
|
5440
|
+
flex: 1
|
|
5441
|
+
},
|
|
5442
|
+
backdrop: {
|
|
5443
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
5444
|
+
backgroundColor: "#000"
|
|
5445
|
+
},
|
|
5446
|
+
imageWrap: {
|
|
5447
|
+
alignItems: "center",
|
|
5448
|
+
justifyContent: "center",
|
|
5449
|
+
overflow: "hidden"
|
|
5450
|
+
},
|
|
5451
|
+
closeButton: {
|
|
5452
|
+
position: "absolute",
|
|
5453
|
+
right: s(12),
|
|
5454
|
+
width: s(40),
|
|
5455
|
+
height: s(40),
|
|
5456
|
+
borderRadius: s(20),
|
|
5457
|
+
backgroundColor: "rgba(0,0,0,0.4)",
|
|
5458
|
+
alignItems: "center",
|
|
5459
|
+
justifyContent: "center"
|
|
5460
|
+
},
|
|
5461
|
+
dots: {
|
|
5462
|
+
position: "absolute",
|
|
5463
|
+
left: 0,
|
|
5464
|
+
right: 0,
|
|
5465
|
+
alignItems: "center"
|
|
5466
|
+
}
|
|
5467
|
+
});
|
|
4289
5468
|
|
|
4290
5469
|
// src/utils/typography.ts
|
|
4291
5470
|
function getResponsiveFontSize(text, maxSize, steps = [
|
|
@@ -4315,6 +5494,7 @@ Object.defineProperty(exports, "toast", {
|
|
|
4315
5494
|
});
|
|
4316
5495
|
exports.Accordion = Accordion;
|
|
4317
5496
|
exports.AlertBanner = AlertBanner;
|
|
5497
|
+
exports.AppHeader = AppHeader;
|
|
4318
5498
|
exports.Avatar = Avatar;
|
|
4319
5499
|
exports.BREAKPOINTS = BREAKPOINTS;
|
|
4320
5500
|
exports.Badge = Badge;
|
|
@@ -4333,9 +5513,9 @@ exports.ChipGroup = ChipGroup;
|
|
|
4333
5513
|
exports.ConfirmDialog = ConfirmDialog;
|
|
4334
5514
|
exports.CurrencyDisplay = CurrencyDisplay;
|
|
4335
5515
|
exports.CurrencyInput = CurrencyInput;
|
|
4336
|
-
exports.CurrencyInputLarge = CurrencyInput;
|
|
4337
5516
|
exports.DetailRow = DetailRow;
|
|
4338
5517
|
exports.EmptyState = EmptyState;
|
|
5518
|
+
exports.ErrorBoundary = ErrorBoundary;
|
|
4339
5519
|
exports.Form = Form;
|
|
4340
5520
|
exports.FormField = FormField;
|
|
4341
5521
|
exports.FormFooter = FormFooter;
|
|
@@ -4343,6 +5523,7 @@ exports.FormSection = FormSection;
|
|
|
4343
5523
|
exports.ICON_SIZES = ICON_SIZES;
|
|
4344
5524
|
exports.Icon = Icon;
|
|
4345
5525
|
exports.IconButton = IconButton;
|
|
5526
|
+
exports.ImageViewer = ImageViewer;
|
|
4346
5527
|
exports.Input = Input;
|
|
4347
5528
|
exports.LabelValue = LabelValue;
|
|
4348
5529
|
exports.ListGroup = ListGroup;
|
|
@@ -4355,13 +5536,17 @@ exports.MenuGroupFooter = MenuGroupFooter;
|
|
|
4355
5536
|
exports.MenuGroupHeader = MenuGroupHeader;
|
|
4356
5537
|
exports.MenuItem = MenuItem;
|
|
4357
5538
|
exports.MonthPicker = MonthPicker;
|
|
4358
|
-
exports.
|
|
5539
|
+
exports.PagerDots = PagerDots;
|
|
5540
|
+
exports.Pressable = Pressable3;
|
|
5541
|
+
exports.PricingCard = PricingCard;
|
|
4359
5542
|
exports.Progress = Progress;
|
|
4360
5543
|
exports.RADIUS = RADIUS;
|
|
4361
5544
|
exports.RadioGroup = RadioGroup;
|
|
5545
|
+
exports.RetrayProvider = RetrayProvider;
|
|
4362
5546
|
exports.SHADOWS = SHADOWS;
|
|
4363
5547
|
exports.SPACING = SPACING;
|
|
4364
5548
|
exports.Select = Select;
|
|
5549
|
+
exports.SelectableGrid = SelectableGrid;
|
|
4365
5550
|
exports.Separator = Separator;
|
|
4366
5551
|
exports.Sheet = Sheet;
|
|
4367
5552
|
exports.Skeleton = Skeleton;
|
|
@@ -4369,6 +5554,7 @@ exports.Slider = Slider;
|
|
|
4369
5554
|
exports.Spinner = Spinner;
|
|
4370
5555
|
exports.Switch = Switch;
|
|
4371
5556
|
exports.TYPOGRAPHY = TYPOGRAPHY;
|
|
5557
|
+
exports.TabBar = TabBar;
|
|
4372
5558
|
exports.Tabs = Tabs;
|
|
4373
5559
|
exports.TabsContent = TabsContent;
|
|
4374
5560
|
exports.Text = Text3;
|
|
@@ -4378,10 +5564,20 @@ exports.ToastProvider = ToastProvider;
|
|
|
4378
5564
|
exports.Toggle = Toggle;
|
|
4379
5565
|
exports.VirtualList = VirtualList;
|
|
4380
5566
|
exports.configureIconFamilies = configureIconFamilies;
|
|
5567
|
+
exports.dateToMonthPickerValue = dateToMonthPickerValue;
|
|
4381
5568
|
exports.defaultDark = defaultDark;
|
|
4382
5569
|
exports.defaultLight = defaultLight;
|
|
4383
5570
|
exports.deriveColors = deriveColors;
|
|
4384
5571
|
exports.getResponsiveFontSize = getResponsiveFontSize;
|
|
5572
|
+
exports.impactHeavy = impactHeavy;
|
|
5573
|
+
exports.impactLight = impactLight;
|
|
5574
|
+
exports.impactMedium = impactMedium;
|
|
5575
|
+
exports.monthPickerValueToDate = monthPickerValueToDate;
|
|
5576
|
+
exports.notificationError = notificationError;
|
|
5577
|
+
exports.notificationSuccess = notificationSuccess;
|
|
5578
|
+
exports.notificationWarning = notificationWarning;
|
|
4385
5579
|
exports.renderIcon = renderIcon;
|
|
5580
|
+
exports.richHaptics = richHaptics;
|
|
5581
|
+
exports.selectionAsync = selectionAsync;
|
|
4386
5582
|
exports.useTheme = useTheme;
|
|
4387
5583
|
exports.useToast = useToast;
|