@retray-dev/ui-kit 10.0.0 → 10.1.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 +15 -13
- package/CONSUMER.md +1 -1
- package/dist/Accordion.d.mts +1 -1
- package/dist/Accordion.d.ts +1 -1
- package/dist/Accordion.js +2 -2
- package/dist/Accordion.mjs +1 -1
- package/dist/ConfirmDialog.d.mts +6 -1
- package/dist/ConfirmDialog.d.ts +6 -1
- package/dist/ConfirmDialog.js +44 -14
- package/dist/ConfirmDialog.mjs +1 -1
- package/dist/ImageViewer.js +282 -141
- package/dist/ImageViewer.mjs +3 -1
- package/dist/Sheet.js +16 -13
- package/dist/Sheet.mjs +1 -1
- package/dist/Switch.js +40 -17
- package/dist/Switch.mjs +1 -1
- package/dist/{chunk-O3HA6TYM.mjs → chunk-DJ7RN37L.mjs} +2 -2
- package/dist/{chunk-FZZLPJ6B.mjs → chunk-KZL5VTYK.mjs} +43 -14
- package/dist/{chunk-QKH5ZOD5.mjs → chunk-WF2XDFRK.mjs} +40 -17
- package/dist/{chunk-Z4BVUWW6.mjs → chunk-WOEYDUJZ.mjs} +19 -31
- package/dist/{chunk-PFZTM6D5.mjs → chunk-Y2NS74WS.mjs} +9 -7
- package/dist/index.js +119 -76
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +7 -3
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +61 -23
- package/src/components/ImageViewer/ImageViewer.tsx +25 -30
- package/src/components/Sheet/Sheet.tsx +10 -9
- package/src/components/Switch/Switch.tsx +30 -17
package/dist/ImageViewer.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React5 = require('react');
|
|
4
4
|
var reactNative = require('react-native');
|
|
5
5
|
var reactNativeGestureHandler = require('react-native-gesture-handler');
|
|
6
6
|
var Animated2 = require('react-native-reanimated');
|
|
7
7
|
var reactNativeSafeAreaContext = require('react-native-safe-area-context');
|
|
8
|
+
var reactNativeSizeMatters = require('react-native-size-matters');
|
|
8
9
|
var AntDesign = require('@expo/vector-icons/AntDesign');
|
|
9
10
|
var Entypo = require('@expo/vector-icons/Entypo');
|
|
10
11
|
var Feather = require('@expo/vector-icons/Feather');
|
|
11
12
|
var FontAwesome5 = require('@expo/vector-icons/FontAwesome5');
|
|
12
13
|
var MaterialIcons = require('@expo/vector-icons/MaterialIcons');
|
|
13
14
|
var Ionicons = require('@expo/vector-icons/Ionicons');
|
|
14
|
-
var
|
|
15
|
+
var pressto = require('pressto');
|
|
15
16
|
|
|
16
17
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
18
|
|
|
18
|
-
var
|
|
19
|
+
var React5__default = /*#__PURE__*/_interopDefault(React5);
|
|
19
20
|
var Animated2__default = /*#__PURE__*/_interopDefault(Animated2);
|
|
20
21
|
var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
|
|
21
22
|
var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
|
|
@@ -30,46 +31,69 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
30
31
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
31
32
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
32
33
|
});
|
|
33
|
-
var
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var resolvedCache = null;
|
|
44
|
-
function buildCache() {
|
|
45
|
-
const cache = /* @__PURE__ */ new Map();
|
|
46
|
-
for (const family of activeFamilies) {
|
|
47
|
-
const glyphMap = family.getGlyphMap();
|
|
48
|
-
for (const iconName of Object.keys(glyphMap)) {
|
|
49
|
-
cache.set(iconName, family);
|
|
34
|
+
var _haptics = null;
|
|
35
|
+
var _hapticsLoaded = false;
|
|
36
|
+
async function getHaptics() {
|
|
37
|
+
if (reactNative.Platform.OS === "web") return null;
|
|
38
|
+
if (!_hapticsLoaded) {
|
|
39
|
+
_hapticsLoaded = true;
|
|
40
|
+
try {
|
|
41
|
+
_haptics = await import('expo-haptics');
|
|
42
|
+
} catch {
|
|
43
|
+
_haptics = null;
|
|
50
44
|
}
|
|
51
45
|
}
|
|
52
|
-
return
|
|
46
|
+
return _haptics;
|
|
53
47
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
var _pulsar = null;
|
|
49
|
+
var _pulsarChecked = false;
|
|
50
|
+
var _pulsarAvailable = false;
|
|
51
|
+
function isPulsarNativeRegistered() {
|
|
52
|
+
try {
|
|
53
|
+
const g = globalThis;
|
|
54
|
+
if (typeof g.__turboModuleProxy === "function") {
|
|
55
|
+
return g.__turboModuleProxy("RNPulsar") != null;
|
|
56
|
+
}
|
|
57
|
+
return reactNative.NativeModules?.RNPulsar != null;
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
57
60
|
}
|
|
58
|
-
return resolvedCache.get(name) ?? null;
|
|
59
61
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
function getPulsar() {
|
|
63
|
+
if (reactNative.Platform.OS === "web") return null;
|
|
64
|
+
if (!_pulsarChecked) {
|
|
65
|
+
_pulsarChecked = true;
|
|
66
|
+
try {
|
|
67
|
+
if (isPulsarNativeRegistered()) {
|
|
68
|
+
_pulsar = __require("react-native-pulsar");
|
|
69
|
+
_pulsarAvailable = true;
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
_pulsar = null;
|
|
73
|
+
_pulsarAvailable = false;
|
|
74
|
+
}
|
|
66
75
|
}
|
|
67
|
-
|
|
68
|
-
const Component = resolved.component;
|
|
69
|
-
return React4__default.default.createElement(Component, { name, size, color });
|
|
76
|
+
return _pulsarAvailable ? _pulsar : null;
|
|
70
77
|
}
|
|
71
|
-
function
|
|
72
|
-
|
|
78
|
+
function selectionAsync() {
|
|
79
|
+
if (reactNative.Platform.OS === "web") return;
|
|
80
|
+
getHaptics().then((h) => {
|
|
81
|
+
if (h) {
|
|
82
|
+
h.selectionAsync();
|
|
83
|
+
} else {
|
|
84
|
+
getPulsar()?.Presets.System.selection();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function impactLight() {
|
|
89
|
+
if (reactNative.Platform.OS === "web") return;
|
|
90
|
+
getHaptics().then((h) => {
|
|
91
|
+
if (h) {
|
|
92
|
+
h.impactAsync(h.ImpactFeedbackStyle.Light);
|
|
93
|
+
} else {
|
|
94
|
+
getPulsar()?.Presets.System.impactLight();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
73
97
|
}
|
|
74
98
|
|
|
75
99
|
// src/theme/colorUtils.ts
|
|
@@ -179,12 +203,12 @@ function deriveColors(t, scheme) {
|
|
|
179
203
|
}
|
|
180
204
|
|
|
181
205
|
// src/theme/ThemeProvider.tsx
|
|
182
|
-
var ThemeContext =
|
|
206
|
+
var ThemeContext = React5.createContext({
|
|
183
207
|
colors: deriveColors(defaultLight, "light"),
|
|
184
208
|
colorScheme: "light"
|
|
185
209
|
});
|
|
186
210
|
function useTheme() {
|
|
187
|
-
const context =
|
|
211
|
+
const context = React5.useContext(ThemeContext);
|
|
188
212
|
if (!context) {
|
|
189
213
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
190
214
|
}
|
|
@@ -193,6 +217,48 @@ function useTheme() {
|
|
|
193
217
|
var isWeb = reactNative.Platform.OS === "web";
|
|
194
218
|
var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
|
|
195
219
|
var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
|
|
220
|
+
var ms = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateScale;
|
|
221
|
+
var glyphMapOf = (mod) => mod.glyphMap ?? {};
|
|
222
|
+
var ALL_FAMILIES = [
|
|
223
|
+
{ name: "Ionicons", component: Ionicons__default.default, getGlyphMap: () => glyphMapOf(Ionicons__default.default) },
|
|
224
|
+
{ name: "MaterialIcons", component: MaterialIcons__default.default, getGlyphMap: () => glyphMapOf(MaterialIcons__default.default) },
|
|
225
|
+
{ name: "FontAwesome5", component: FontAwesome5__default.default, getGlyphMap: () => glyphMapOf(FontAwesome5__default.default) },
|
|
226
|
+
{ name: "Entypo", component: Entypo__default.default, getGlyphMap: () => glyphMapOf(Entypo__default.default) },
|
|
227
|
+
{ name: "AntDesign", component: AntDesign__default.default, getGlyphMap: () => glyphMapOf(AntDesign__default.default) },
|
|
228
|
+
{ name: "Feather", component: Feather__default.default, getGlyphMap: () => glyphMapOf(Feather__default.default) }
|
|
229
|
+
];
|
|
230
|
+
var activeFamilies = ALL_FAMILIES;
|
|
231
|
+
var resolvedCache = null;
|
|
232
|
+
function buildCache() {
|
|
233
|
+
const cache = /* @__PURE__ */ new Map();
|
|
234
|
+
for (const family of activeFamilies) {
|
|
235
|
+
const glyphMap = family.getGlyphMap();
|
|
236
|
+
for (const iconName of Object.keys(glyphMap)) {
|
|
237
|
+
cache.set(iconName, family);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return cache;
|
|
241
|
+
}
|
|
242
|
+
function resolveFamily(name) {
|
|
243
|
+
if (!resolvedCache) {
|
|
244
|
+
resolvedCache = buildCache();
|
|
245
|
+
}
|
|
246
|
+
return resolvedCache.get(name) ?? null;
|
|
247
|
+
}
|
|
248
|
+
function Icon({ name, size, color, family }) {
|
|
249
|
+
let resolved = null;
|
|
250
|
+
if (family) {
|
|
251
|
+
resolved = ALL_FAMILIES.find((f) => f.name === family) ?? null;
|
|
252
|
+
} else {
|
|
253
|
+
resolved = resolveFamily(name);
|
|
254
|
+
}
|
|
255
|
+
if (!resolved) return null;
|
|
256
|
+
const Component = resolved.component;
|
|
257
|
+
return React5__default.default.createElement(Component, { name, size, color });
|
|
258
|
+
}
|
|
259
|
+
function renderIcon(name, size, color) {
|
|
260
|
+
return React5__default.default.createElement(Icon, { name, size, color });
|
|
261
|
+
}
|
|
196
262
|
var SPRINGS = {
|
|
197
263
|
/** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
|
|
198
264
|
glide: { stiffness: 380, damping: 38, mass: 1 }};
|
|
@@ -204,78 +270,165 @@ var SPRINGS = {
|
|
|
204
270
|
/** Quick ease-in for collapsing. */
|
|
205
271
|
collapse: Animated2.Easing.in(Animated2.Easing.ease)
|
|
206
272
|
});
|
|
207
|
-
var
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
273
|
+
var PRESS_SCALE = {
|
|
274
|
+
button: 0.95,
|
|
275
|
+
card: 0.98,
|
|
276
|
+
row: 0.97,
|
|
277
|
+
chip: 0.94
|
|
278
|
+
};
|
|
279
|
+
var PressableButton = pressto.createAnimatedPressable((progress) => {
|
|
280
|
+
"worklet";
|
|
281
|
+
const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
|
|
282
|
+
return { transform: [{ scale: scale2 }] };
|
|
283
|
+
});
|
|
284
|
+
pressto.createAnimatedPressable((progress) => {
|
|
285
|
+
"worklet";
|
|
286
|
+
const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
|
|
287
|
+
return { transform: [{ scale: scale2 }] };
|
|
288
|
+
});
|
|
289
|
+
pressto.createAnimatedPressable((progress) => {
|
|
290
|
+
"worklet";
|
|
291
|
+
const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
|
|
292
|
+
return { transform: [{ scale: scale2 }] };
|
|
293
|
+
});
|
|
294
|
+
pressto.createAnimatedPressable((progress) => {
|
|
295
|
+
"worklet";
|
|
296
|
+
const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
|
|
297
|
+
return { transform: [{ scale: scale2 }] };
|
|
298
|
+
});
|
|
299
|
+
pressto.createAnimatedPressable((progress) => {
|
|
300
|
+
"worklet";
|
|
301
|
+
const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
|
|
302
|
+
return { transform: [{ scale: scale2 }] };
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// src/components/IconButton/IconButton.tsx
|
|
306
|
+
var sizeMap = {
|
|
307
|
+
// AUDIT FIX: sm was 32pt — below Apple HIG 44pt minimum touch target.
|
|
308
|
+
sm: { container: s(44), icon: 18 },
|
|
309
|
+
md: { container: s(44), icon: 20 },
|
|
310
|
+
lg: { container: s(52), icon: 24 }
|
|
311
|
+
};
|
|
312
|
+
function IconButtonBase({
|
|
313
|
+
iconName,
|
|
314
|
+
icon,
|
|
315
|
+
iconColor,
|
|
316
|
+
variant = "primary",
|
|
317
|
+
size = "md",
|
|
318
|
+
loading = false,
|
|
319
|
+
badge,
|
|
320
|
+
disabled,
|
|
321
|
+
style,
|
|
322
|
+
onPress,
|
|
323
|
+
accessibilityLabel,
|
|
324
|
+
accessibilityHint
|
|
325
|
+
}) {
|
|
326
|
+
const { colors } = useTheme();
|
|
327
|
+
const isDisabled = disabled || loading;
|
|
328
|
+
const handlePress = () => {
|
|
329
|
+
impactLight();
|
|
330
|
+
onPress?.();
|
|
331
|
+
};
|
|
332
|
+
const containerVariantStyle = {
|
|
333
|
+
primary: { backgroundColor: colors.primary },
|
|
334
|
+
secondary: { backgroundColor: colors.surface },
|
|
335
|
+
outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.border },
|
|
336
|
+
text: { backgroundColor: "transparent" },
|
|
337
|
+
destructive: { backgroundColor: colors.destructive }
|
|
338
|
+
}[variant];
|
|
339
|
+
const defaultIconColor = {
|
|
340
|
+
primary: colors.primaryForeground,
|
|
341
|
+
secondary: colors.foreground,
|
|
342
|
+
outline: colors.foreground,
|
|
343
|
+
text: colors.foreground,
|
|
344
|
+
destructive: colors.destructiveForeground
|
|
345
|
+
}[variant];
|
|
346
|
+
const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.foreground;
|
|
347
|
+
const { container: containerSize, icon: iconSize } = sizeMap[size];
|
|
348
|
+
const resolvedIcon = iconName ? renderIcon(iconName, iconSize, iconColor ?? defaultIconColor) : icon;
|
|
349
|
+
const showBadge = badge !== void 0 && badge !== false && badge !== 0;
|
|
350
|
+
const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
|
|
351
|
+
const showCount = typeof badge === "number" && badge > 0;
|
|
352
|
+
return /* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: styles.wrapper }, /* @__PURE__ */ React5__default.default.createElement(
|
|
353
|
+
PressableButton,
|
|
354
|
+
{
|
|
355
|
+
style: [
|
|
356
|
+
styles.base,
|
|
357
|
+
containerVariantStyle,
|
|
358
|
+
{ width: containerSize, height: containerSize },
|
|
359
|
+
isDisabled && styles.disabled,
|
|
360
|
+
style
|
|
361
|
+
],
|
|
362
|
+
enabled: !isDisabled,
|
|
363
|
+
onPress: handlePress,
|
|
364
|
+
rippleColor: "transparent",
|
|
365
|
+
touchSoundDisabled: true,
|
|
366
|
+
activateOnHover: true,
|
|
367
|
+
accessibilityRole: "button",
|
|
368
|
+
accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
|
|
369
|
+
accessibilityHint,
|
|
370
|
+
accessibilityState: { disabled: isDisabled, busy: loading }
|
|
371
|
+
},
|
|
372
|
+
loading ? /* @__PURE__ */ React5__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
|
|
373
|
+
), showBadge && /* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: [
|
|
374
|
+
styles.badge,
|
|
375
|
+
{ backgroundColor: colors.primary },
|
|
376
|
+
showCount ? styles.badgeCount : styles.badgeDot
|
|
377
|
+
] }, showCount && /* @__PURE__ */ React5__default.default.createElement(reactNative.Text, { style: [styles.badgeText, { color: colors.primaryForeground }] }, badgeCount)));
|
|
234
378
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
379
|
+
var IconButton = React5__default.default.memo(IconButtonBase);
|
|
380
|
+
var styles = reactNative.StyleSheet.create({
|
|
381
|
+
wrapper: {
|
|
382
|
+
alignSelf: "flex-start"
|
|
383
|
+
},
|
|
384
|
+
base: {
|
|
385
|
+
borderRadius: 9999,
|
|
386
|
+
alignItems: "center",
|
|
387
|
+
justifyContent: "center"
|
|
388
|
+
},
|
|
389
|
+
disabled: {
|
|
390
|
+
opacity: 0.45
|
|
391
|
+
},
|
|
392
|
+
badge: {
|
|
393
|
+
position: "absolute",
|
|
394
|
+
top: -2,
|
|
395
|
+
right: -2,
|
|
396
|
+
alignItems: "center",
|
|
397
|
+
justifyContent: "center"
|
|
398
|
+
},
|
|
399
|
+
badgeDot: {
|
|
400
|
+
width: 8,
|
|
401
|
+
height: 8,
|
|
402
|
+
borderRadius: 9999
|
|
403
|
+
},
|
|
404
|
+
badgeCount: {
|
|
405
|
+
minWidth: 16,
|
|
406
|
+
height: 16,
|
|
407
|
+
borderRadius: 9999,
|
|
408
|
+
paddingHorizontal: 3
|
|
409
|
+
},
|
|
410
|
+
badgeText: {
|
|
411
|
+
fontFamily: "Sohne-Bold",
|
|
412
|
+
fontSize: ms(9),
|
|
413
|
+
lineHeight: 14
|
|
248
414
|
}
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
function selectionAsync() {
|
|
252
|
-
if (reactNative.Platform.OS === "web") return;
|
|
253
|
-
getHaptics().then((h) => {
|
|
254
|
-
if (h) {
|
|
255
|
-
h.selectionAsync();
|
|
256
|
-
} else {
|
|
257
|
-
getPulsar()?.Presets.System.selection();
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// src/components/PagerDots/PagerDots.tsx
|
|
415
|
+
});
|
|
263
416
|
function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }) {
|
|
264
417
|
const progress = Animated2.useSharedValue(active ? 1 : 0);
|
|
265
|
-
|
|
418
|
+
React5.useEffect(() => {
|
|
266
419
|
progress.value = Animated2.withSpring(active ? 1 : 0, SPRINGS.glide);
|
|
267
420
|
}, [active, progress]);
|
|
268
421
|
const animatedStyle = Animated2.useAnimatedStyle(() => ({
|
|
269
422
|
width: size + progress.value * size * 1.5,
|
|
270
423
|
backgroundColor: Animated2.interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor])
|
|
271
424
|
}));
|
|
272
|
-
const dot = /* @__PURE__ */
|
|
425
|
+
const dot = /* @__PURE__ */ React5__default.default.createElement(Animated2__default.default.View, { style: [{ height: size, borderRadius: size / 2 }, animatedStyle] });
|
|
273
426
|
if (!onPress) return dot;
|
|
274
427
|
const handlePress = () => {
|
|
275
428
|
selectionAsync();
|
|
276
429
|
onPress();
|
|
277
430
|
};
|
|
278
|
-
return /* @__PURE__ */
|
|
431
|
+
return /* @__PURE__ */ React5__default.default.createElement(
|
|
279
432
|
reactNative.TouchableOpacity,
|
|
280
433
|
{
|
|
281
434
|
onPress: handlePress,
|
|
@@ -324,14 +477,14 @@ function PagerDots({
|
|
|
324
477
|
onDotPress(activeIndex + 1);
|
|
325
478
|
}
|
|
326
479
|
};
|
|
327
|
-
return /* @__PURE__ */
|
|
480
|
+
return /* @__PURE__ */ React5__default.default.createElement(
|
|
328
481
|
reactNative.View,
|
|
329
482
|
{
|
|
330
|
-
style: [
|
|
483
|
+
style: [styles2.container, { gap: s(spacing) }, style],
|
|
331
484
|
accessibilityRole: "adjustable",
|
|
332
485
|
accessibilityLabel: `Page ${activeIndex + 1} of ${count}`
|
|
333
486
|
},
|
|
334
|
-
hasControls && /* @__PURE__ */
|
|
487
|
+
hasControls && /* @__PURE__ */ React5__default.default.createElement(
|
|
335
488
|
reactNative.TouchableOpacity,
|
|
336
489
|
{
|
|
337
490
|
onPress: handlePrevious,
|
|
@@ -341,11 +494,11 @@ function PagerDots({
|
|
|
341
494
|
accessibilityRole: "button",
|
|
342
495
|
accessibilityLabel: "Previous page",
|
|
343
496
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
344
|
-
style: [
|
|
497
|
+
style: [styles2.controlBtn, !canGoPrev && styles2.controlBtnDisabled]
|
|
345
498
|
},
|
|
346
499
|
renderIcon("chevron-left", s(18), canGoPrev ? colors.foreground : colors.foregroundMuted)
|
|
347
500
|
),
|
|
348
|
-
/* @__PURE__ */
|
|
501
|
+
/* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: [styles2.dotsRow, { gap: s(spacing) }] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React5__default.default.createElement(
|
|
349
502
|
Dot,
|
|
350
503
|
{
|
|
351
504
|
key: i,
|
|
@@ -358,7 +511,7 @@ function PagerDots({
|
|
|
358
511
|
onPress: onDotPress ? () => onDotPress(i) : void 0
|
|
359
512
|
}
|
|
360
513
|
))),
|
|
361
|
-
hasControls && /* @__PURE__ */
|
|
514
|
+
hasControls && /* @__PURE__ */ React5__default.default.createElement(
|
|
362
515
|
reactNative.TouchableOpacity,
|
|
363
516
|
{
|
|
364
517
|
onPress: handleNext,
|
|
@@ -368,13 +521,13 @@ function PagerDots({
|
|
|
368
521
|
accessibilityRole: "button",
|
|
369
522
|
accessibilityLabel: "Next page",
|
|
370
523
|
hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
|
|
371
|
-
style: [
|
|
524
|
+
style: [styles2.controlBtn, !canGoNext && styles2.controlBtnDisabled]
|
|
372
525
|
},
|
|
373
526
|
renderIcon("chevron-right", s(18), canGoNext ? colors.foreground : colors.foregroundMuted)
|
|
374
527
|
)
|
|
375
528
|
);
|
|
376
529
|
}
|
|
377
|
-
var
|
|
530
|
+
var styles2 = reactNative.StyleSheet.create({
|
|
378
531
|
container: {
|
|
379
532
|
flexDirection: "row",
|
|
380
533
|
alignItems: "center",
|
|
@@ -402,7 +555,7 @@ function ZoomableImage({ source, width, height, onZoomChange }) {
|
|
|
402
555
|
const translateY = Animated2.useSharedValue(0);
|
|
403
556
|
const savedX = Animated2.useSharedValue(0);
|
|
404
557
|
const savedY = Animated2.useSharedValue(0);
|
|
405
|
-
const reportZoom =
|
|
558
|
+
const reportZoom = React5.useCallback((zoomed) => onZoomChange(zoomed), [onZoomChange]);
|
|
406
559
|
const reset = () => {
|
|
407
560
|
"worklet";
|
|
408
561
|
scale2.value = Animated2.withTiming(1);
|
|
@@ -448,22 +601,17 @@ function ZoomableImage({ source, width, height, onZoomChange }) {
|
|
|
448
601
|
{ scale: scale2.value }
|
|
449
602
|
]
|
|
450
603
|
}));
|
|
451
|
-
return /* @__PURE__ */
|
|
452
|
-
Animated2__default.default.Image,
|
|
453
|
-
{
|
|
454
|
-
source,
|
|
455
|
-
style: [{ width, height }, animatedStyle],
|
|
456
|
-
resizeMode: "contain"
|
|
457
|
-
}
|
|
458
|
-
)));
|
|
604
|
+
return /* @__PURE__ */ React5__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: composed }, /* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: [{ width, height }, styles3.imageWrap], collapsable: false }, /* @__PURE__ */ React5__default.default.createElement(Animated2__default.default.View, { style: [{ width, height }, animatedStyle] }, /* @__PURE__ */ React5__default.default.createElement(reactNative.Image, { source, style: { width, height }, resizeMode: "contain" }))));
|
|
459
605
|
}
|
|
460
606
|
function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
461
|
-
const
|
|
607
|
+
const window = reactNative.useWindowDimensions();
|
|
608
|
+
const width = window.width > 0 ? window.width : reactNative.Dimensions.get("window").width;
|
|
609
|
+
const height = window.height > 0 ? window.height : reactNative.Dimensions.get("window").height;
|
|
462
610
|
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
463
|
-
const [index, setIndex] =
|
|
464
|
-
const [pagingEnabled, setPagingEnabled] =
|
|
465
|
-
const scrollRef =
|
|
466
|
-
|
|
611
|
+
const [index, setIndex] = React5.useState(initialIndex);
|
|
612
|
+
const [pagingEnabled, setPagingEnabled] = React5.useState(true);
|
|
613
|
+
const scrollRef = React5__default.default.useRef(null);
|
|
614
|
+
React5__default.default.useEffect(() => {
|
|
467
615
|
if (!visible) return;
|
|
468
616
|
const handle = requestAnimationFrame(() => {
|
|
469
617
|
setIndex(initialIndex);
|
|
@@ -474,7 +622,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
|
474
622
|
}, [visible, initialIndex, width]);
|
|
475
623
|
const dragY = Animated2.useSharedValue(0);
|
|
476
624
|
const DISMISS_THRESHOLD = height * 0.18;
|
|
477
|
-
const closeViewer =
|
|
625
|
+
const closeViewer = React5.useCallback(() => onClose(), [onClose]);
|
|
478
626
|
const swipeDown = reactNativeGestureHandler.Gesture.Pan().enabled(pagingEnabled).activeOffsetY(12).failOffsetX([-16, 16]).onUpdate((e) => {
|
|
479
627
|
dragY.value = Math.max(0, e.translationY);
|
|
480
628
|
}).onEnd((e) => {
|
|
@@ -484,7 +632,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
|
484
632
|
dragY.value = Animated2.withTiming(0);
|
|
485
633
|
}
|
|
486
634
|
});
|
|
487
|
-
|
|
635
|
+
React5__default.default.useEffect(() => {
|
|
488
636
|
if (visible) dragY.value = 0;
|
|
489
637
|
}, [visible, dragY]);
|
|
490
638
|
const dismissStyle = Animated2.useAnimatedStyle(() => ({
|
|
@@ -501,7 +649,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
|
501
649
|
scrollRef.current?.scrollTo({ x: page * width, animated: true });
|
|
502
650
|
setIndex(page);
|
|
503
651
|
};
|
|
504
|
-
return /* @__PURE__ */
|
|
652
|
+
return /* @__PURE__ */ React5__default.default.createElement(reactNative.Modal, { visible, transparent: false, animationType: "fade", onRequestClose: onClose, statusBarTranslucent: true }, /* @__PURE__ */ React5__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles3.root }, /* @__PURE__ */ React5__default.default.createElement(Animated2__default.default.View, { style: [styles3.backdrop, backdropStyle], pointerEvents: "none" }), /* @__PURE__ */ React5__default.default.createElement(Animated2__default.default.View, { style: [styles3.container, dismissStyle] }, /* @__PURE__ */ React5__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: swipeDown }, /* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: styles3.root, collapsable: false }, /* @__PURE__ */ React5__default.default.createElement(
|
|
505
653
|
reactNative.ScrollView,
|
|
506
654
|
{
|
|
507
655
|
ref: scrollRef,
|
|
@@ -512,7 +660,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
|
512
660
|
onMomentumScrollEnd: onMomentumEnd,
|
|
513
661
|
bounces: false
|
|
514
662
|
},
|
|
515
|
-
images.map((source, i) => /* @__PURE__ */
|
|
663
|
+
images.map((source, i) => /* @__PURE__ */ React5__default.default.createElement(
|
|
516
664
|
ZoomableImage,
|
|
517
665
|
{
|
|
518
666
|
key: i,
|
|
@@ -522,19 +670,18 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
|
522
670
|
onZoomChange: (zoomed) => setPagingEnabled(!zoomed)
|
|
523
671
|
}
|
|
524
672
|
))
|
|
525
|
-
))), /* @__PURE__ */
|
|
526
|
-
|
|
673
|
+
))), /* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: [styles3.closeButtonWrapper, { top: insets.top + vs(8) }] }, /* @__PURE__ */ React5__default.default.createElement(
|
|
674
|
+
IconButton,
|
|
527
675
|
{
|
|
528
|
-
|
|
676
|
+
iconName: "x",
|
|
677
|
+
size: "md",
|
|
678
|
+
variant: "text",
|
|
679
|
+
style: { backgroundColor: "rgba(255,255,255,0.18)" },
|
|
680
|
+
iconColor: "#fff",
|
|
529
681
|
onPress: onClose,
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
accessibilityLabel: "Close",
|
|
534
|
-
hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
|
|
535
|
-
},
|
|
536
|
-
renderIcon("x", 26, "#fff")
|
|
537
|
-
), images.length > 1 ? /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.dots, { bottom: insets.bottom + vs(16) }], pointerEvents: "box-none" }, /* @__PURE__ */ React4__default.default.createElement(
|
|
682
|
+
accessibilityLabel: "Close"
|
|
683
|
+
}
|
|
684
|
+
)), images.length > 1 ? /* @__PURE__ */ React5__default.default.createElement(reactNative.View, { style: [styles3.dots, { bottom: insets.bottom + vs(16) }], pointerEvents: "box-none" }, /* @__PURE__ */ React5__default.default.createElement(
|
|
538
685
|
PagerDots,
|
|
539
686
|
{
|
|
540
687
|
count: images.length,
|
|
@@ -545,7 +692,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
|
|
|
545
692
|
}
|
|
546
693
|
)) : null)));
|
|
547
694
|
}
|
|
548
|
-
var
|
|
695
|
+
var styles3 = reactNative.StyleSheet.create({
|
|
549
696
|
root: {
|
|
550
697
|
flex: 1
|
|
551
698
|
},
|
|
@@ -561,15 +708,9 @@ var styles2 = reactNative.StyleSheet.create({
|
|
|
561
708
|
justifyContent: "center",
|
|
562
709
|
overflow: "hidden"
|
|
563
710
|
},
|
|
564
|
-
|
|
711
|
+
closeButtonWrapper: {
|
|
565
712
|
position: "absolute",
|
|
566
|
-
right: s(12)
|
|
567
|
-
width: s(40),
|
|
568
|
-
height: s(40),
|
|
569
|
-
borderRadius: s(20),
|
|
570
|
-
backgroundColor: "rgba(0,0,0,0.4)",
|
|
571
|
-
alignItems: "center",
|
|
572
|
-
justifyContent: "center"
|
|
713
|
+
right: s(12)
|
|
573
714
|
},
|
|
574
715
|
dots: {
|
|
575
716
|
position: "absolute",
|
package/dist/ImageViewer.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export { ImageViewer } from './chunk-
|
|
1
|
+
export { ImageViewer } from './chunk-WOEYDUJZ.mjs';
|
|
2
2
|
import './chunk-4K625MVM.mjs';
|
|
3
|
+
import './chunk-3U4SSNWP.mjs';
|
|
4
|
+
import './chunk-3DKJ2GIC.mjs';
|
|
3
5
|
import './chunk-EJ7ZPXOH.mjs';
|
|
4
6
|
import './chunk-DVK4G2GT.mjs';
|
|
5
7
|
import './chunk-T7XZ7H7Y.mjs';
|