panelui-native 0.98.0 → 0.99.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/src/index.ts CHANGED
@@ -569,6 +569,11 @@ export {
569
569
  type ImageGenerationFieldProps,
570
570
  type ImageGenerationStatus,
571
571
  } from './components/image-generation';
572
+ export {
573
+ ImageViewer,
574
+ type ImageViewerProps,
575
+ type ImageViewerTriggerProps,
576
+ } from './components/image-viewer';
572
577
  export { Input, type InputProps } from './components/input';
573
578
  export {
574
579
  InputGroup,
@@ -17,7 +17,13 @@
17
17
  */
18
18
  import { useEffect, useState, type ComponentType } from 'react';
19
19
  import { AccessibilityInfo, StyleSheet, View, type ViewProps } from 'react-native';
20
- import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
20
+ import Animated, {
21
+ FadeIn,
22
+ FadeOut,
23
+ useAnimatedProps,
24
+ useAnimatedStyle,
25
+ type DerivedValue,
26
+ } from 'react-native-reanimated';
21
27
 
22
28
  type BlurTint = 'light' | 'dark' | 'default' | 'systemMaterial';
23
29
 
@@ -46,6 +52,15 @@ const BlurView: ComponentType<BlurViewProps> | null = (() => {
46
52
  /** True when a real blur can be drawn — for a caller that wants to know. */
47
53
  export const hasBlur = BlurView !== null;
48
54
 
55
+ /**
56
+ * The same view, able to take its `intensity` from the UI thread. The package
57
+ * names the native view as the one to animate, so the radius itself moves
58
+ * rather than a finished blur being faded in over the page.
59
+ */
60
+ const AnimatedBlurView = BlurView
61
+ ? Animated.createAnimatedComponent(BlurView as ComponentType<BlurViewProps>)
62
+ : null;
63
+
49
64
  type ReduceTransparencySource = {
50
65
  isReduceTransparencyEnabled?: () => Promise<boolean>;
51
66
  addEventListener?: (
@@ -160,6 +175,15 @@ export interface ScrimProps extends Omit<ViewProps, 'children'> {
160
175
  * opaque Reduce Transparency fallback. A popover passes a lighter one than a dialog.
161
176
  */
162
177
  dimClassName?: string;
178
+ /**
179
+ * How far the backdrop is in, from `0` to `1`, read on the UI thread.
180
+ *
181
+ * For an overlay the finger can pull partway out — a viewer dragged towards
182
+ * dismissal — where the backdrop has to follow the finger instead of running
183
+ * its own fade. The blur's radius tracks it, and the dim and the opaque
184
+ * fallback track it as opacity. Left out, the scrim fades itself in and out.
185
+ */
186
+ progress?: DerivedValue<number>;
163
187
  }
164
188
 
165
189
  export function Scrim({
@@ -167,12 +191,27 @@ export function Scrim({
167
191
  intensity = 24,
168
192
  tint = 'default',
169
193
  dimClassName = 'bg-black/50',
194
+ progress,
170
195
  style,
171
196
  ...props
172
197
  }: ScrimProps) {
173
198
  const reduceTransparency = useReduceTransparency();
174
199
  const mode = scrimMode(blur, BlurView !== null, reduceTransparency);
175
200
 
201
+ if (progress) {
202
+ return (
203
+ <ProgressScrim
204
+ mode={mode}
205
+ progress={progress}
206
+ intensity={intensity}
207
+ tint={tint}
208
+ dimClassName={dimClassName}
209
+ style={style}
210
+ {...props}
211
+ />
212
+ );
213
+ }
214
+
176
215
  if (mode === 'blur' && BlurView) {
177
216
  return (
178
217
  <Animated.View
@@ -219,3 +258,59 @@ export function Scrim({
219
258
  }
220
259
 
221
260
  Scrim.displayName = 'Scrim';
261
+
262
+ interface ProgressScrimProps extends Omit<ViewProps, 'children'> {
263
+ mode: ScrimMode;
264
+ progress: DerivedValue<number>;
265
+ intensity: number;
266
+ tint: BlurTint;
267
+ dimClassName: string;
268
+ }
269
+
270
+ /** The scrim with its three layers driven by a shared value instead of a fade. */
271
+ function ProgressScrim({
272
+ mode,
273
+ progress,
274
+ intensity,
275
+ tint,
276
+ dimClassName,
277
+ style,
278
+ ...props
279
+ }: ProgressScrimProps) {
280
+ const blurProps = useAnimatedProps(() => ({
281
+ intensity: Math.min(Math.max(progress.value, 0), 1) * intensity,
282
+ }));
283
+ const fade = useAnimatedStyle(() => ({
284
+ opacity: Math.min(Math.max(progress.value, 0), 1),
285
+ }));
286
+
287
+ if (mode === 'blur' && AnimatedBlurView) {
288
+ return (
289
+ <View style={[StyleSheet.absoluteFill, style]} {...props}>
290
+ <AnimatedBlurView
291
+ tint={tint}
292
+ animatedProps={blurProps}
293
+ style={StyleSheet.absoluteFill}
294
+ />
295
+ <Animated.View
296
+ pointerEvents="none"
297
+ style={[StyleSheet.absoluteFill, fade]}
298
+ className="bg-black/10"
299
+ />
300
+ </View>
301
+ );
302
+ }
303
+
304
+ return (
305
+ <Animated.View style={[StyleSheet.absoluteFill, fade, style]} {...props}>
306
+ {mode === 'opaque' ? (
307
+ <View
308
+ pointerEvents="none"
309
+ style={StyleSheet.absoluteFill}
310
+ className={opaqueClassName(tint)}
311
+ />
312
+ ) : null}
313
+ <View pointerEvents="none" style={StyleSheet.absoluteFill} className={dimClassName} />
314
+ </Animated.View>
315
+ );
316
+ }