@expokit/cli 0.4.4 → 0.5.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/README.md +30 -3
- package/bin/expo-kit.js +749 -288
- package/bin/lib.mjs +310 -3
- package/package.json +1 -1
- package/registry/_docs/action-sheet.json +1 -1
- package/registry/_docs/alert.json +6 -0
- package/registry/_docs/bottom-sheet.json +6 -0
- package/registry/_docs/bullet.json +6 -0
- package/registry/_docs/dialog.json +1 -1
- package/registry/_docs/drawer.json +3 -3
- package/registry/_docs/glass-search-bar.json +1 -1
- package/registry/_docs/grain.json +6 -1
- package/registry/_docs/isometric-bar.json +6 -0
- package/registry/_docs/liquidglass-tab.json +1 -1
- package/registry/_docs/password-input.json +1 -1
- package/registry/_docs/pixel-bar.json +6 -0
- package/registry/_docs/polar-area.json +6 -0
- package/registry/_docs/qr-code-button.json +9 -3
- package/registry/_docs/scratch-card.json +7 -1
- package/registry/_docs/search-bar.json +1 -1
- package/registry/_docs/select.json +2 -2
- package/registry/_docs/slide-to-confirm.json +2 -2
- package/registry/_docs/spinner.json +1 -1
- package/registry/_docs/stateful-button.json +2 -2
- package/registry/_docs/swipe-deck.json +1 -1
- package/registry/_docs/time-picker.json +2 -2
- package/registry/_docs/timeline-chart.json +6 -0
- package/registry/_docs/toast.json +15 -3
- package/registry/_docs/treemap.json +6 -0
- package/registry/_docs/waterfall.json +6 -0
- package/registry/accordion/files/src/components/ui/accordion.tsx +6 -4
- package/registry/accordion/files/src/lib/kit.tsx +363 -11
- package/registry/accordion.json +1 -0
- package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +43 -48
- package/registry/action-sheet/files/src/lib/kit.tsx +363 -11
- package/registry/action-sheet.json +1 -0
- package/registry/alert/files/src/components/ui/alert.tsx +19 -12
- package/registry/alert/files/src/lib/kit.tsx +363 -11
- package/registry/alert.json +3 -4
- package/registry/assistant-app.json +1 -0
- package/registry/avatar/files/src/components/ui/avatar.tsx +84 -66
- package/registry/avatar/files/src/lib/kit.tsx +363 -11
- package/registry/avatar.json +1 -0
- package/registry/badge/files/src/components/ui/badge.tsx +34 -34
- package/registry/badge/files/src/lib/kit.tsx +363 -11
- package/registry/badge.json +1 -0
- package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +28 -27
- package/registry/bottom-nav/files/src/lib/kit.tsx +363 -11
- package/registry/bottom-nav.json +5 -0
- package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +353 -289
- package/registry/bottom-sheet/files/src/lib/kit.tsx +363 -11
- package/registry/bottom-sheet.json +5 -1
- package/registry/bullet.json +1 -0
- package/registry/button/files/src/components/ui/button.tsx +18 -16
- package/registry/button/files/src/lib/kit.tsx +363 -11
- package/registry/button-3d/files/src/components/ui/button-3d.tsx +2 -2
- package/registry/button-3d/files/src/lib/kit.tsx +363 -11
- package/registry/button-3d.json +1 -0
- package/registry/button.json +1 -0
- package/registry/calendar/files/src/components/ui/calendar.tsx +74 -76
- package/registry/calendar/files/src/lib/kit.tsx +363 -11
- package/registry/calendar.json +1 -0
- package/registry/card/files/src/components/ui/card.tsx +3 -3
- package/registry/card/files/src/lib/kit.tsx +363 -11
- package/registry/card-stack.json +1 -0
- package/registry/card.json +1 -0
- package/registry/carousel.json +1 -0
- package/registry/chat.json +7 -0
- package/registry/checkbox/files/src/components/ui/checkbox.tsx +4 -4
- package/registry/checkbox/files/src/lib/kit.tsx +363 -11
- package/registry/checkbox.json +1 -0
- package/registry/checkout.json +1 -0
- package/registry/chip-group/files/src/components/ui/chip-group.tsx +22 -22
- package/registry/chip-group/files/src/lib/kit.tsx +363 -11
- package/registry/chip-group.json +1 -0
- package/registry/confetti/files/src/components/ui/confetti.tsx +15 -14
- package/registry/confetti.json +3 -6
- package/registry/coupon/files/src/components/ui/coupon.tsx +42 -42
- package/registry/coupon/files/src/components/ui/flip-card.tsx +6 -5
- package/registry/coupon/files/src/components/ui/tilt-card.tsx +76 -91
- package/registry/coupon/files/src/lib/kit.tsx +363 -11
- package/registry/coupon/files/src/lib/ticket-shape.tsx +54 -44
- package/registry/coupon.json +1 -0
- package/registry/cube-pager.json +1 -0
- package/registry/dashboard.json +1 -0
- package/registry/date-picker/files/src/components/ui/calendar.tsx +74 -76
- package/registry/date-picker/files/src/components/ui/date-picker.tsx +55 -56
- package/registry/date-picker/files/src/lib/kit.tsx +363 -11
- package/registry/date-picker.json +1 -0
- package/registry/dialog/files/src/components/ui/dialog.tsx +60 -56
- package/registry/dialog/files/src/lib/kit.tsx +363 -11
- package/registry/dialog.json +1 -0
- package/registry/donut-shop.json +1 -0
- package/registry/drawer/files/src/components/ui/drawer.tsx +73 -69
- package/registry/drawer/files/src/lib/kit.tsx +363 -11
- package/registry/drawer.json +1 -0
- package/registry/fab.json +1 -0
- package/registry/fintech-app.json +1 -0
- package/registry/flip-calendar/files/src/components/ui/flip-calendar.tsx +92 -86
- package/registry/flip-calendar/files/src/lib/kit.tsx +363 -11
- package/registry/flip-calendar.json +7 -0
- package/registry/flip-card/files/src/components/ui/flip-card.tsx +6 -5
- package/registry/flip-card/files/src/lib/kit.tsx +363 -11
- package/registry/flip-card.json +1 -0
- package/registry/floating-input/files/src/components/ui/floating-input.tsx +33 -33
- package/registry/floating-input/files/src/lib/kit.tsx +363 -11
- package/registry/floating-input.json +1 -0
- package/registry/food-app.json +1 -0
- package/registry/gift-card.json +1 -0
- package/registry/glass-button.json +5 -0
- package/registry/glass-nav-bar.json +1 -0
- package/registry/glass-search-bar.json +1 -0
- package/registry/glass-segmented.json +1 -0
- package/registry/glass-sheet.json +1 -0
- package/registry/glass-tab-bar.json +5 -0
- package/registry/glass.json +1 -0
- package/registry/grain/files/src/components/ui/grain.tsx +16 -14
- package/registry/grain.json +8 -6
- package/registry/inbox.json +1 -0
- package/registry/isometric-bar.json +1 -0
- package/registry/kit/files/src/lib/kit.tsx +363 -11
- package/registry/kit.json +1 -0
- package/registry/liquidglass-tab/files/src/app/_layout.tsx +0 -1
- package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +23 -9
- package/registry/liquidglass-tab/files/src/components/TabScreen.tsx +2 -2
- package/registry/liquidglass-tab/files/src/lib/tab-icons.ts +1 -1
- package/registry/liquidglass-tab.json +1 -0
- package/registry/list-item/files/src/components/ui/list-item.tsx +42 -42
- package/registry/list-item/files/src/lib/kit.tsx +363 -11
- package/registry/list-item.json +1 -0
- package/registry/loyalty-card.json +1 -0
- package/registry/morphing-button-group.json +1 -0
- package/registry/number-ticker.json +1 -0
- package/registry/offers.json +1 -0
- package/registry/onboarding.json +1 -0
- package/registry/orb-reveal.json +1 -0
- package/registry/otp-input/files/src/components/ui/otp-input.tsx +48 -29
- package/registry/otp-input/files/src/lib/kit.tsx +363 -11
- package/registry/otp-input.json +1 -0
- package/registry/parallax-layers.json +1 -0
- package/registry/parallax-scroll.json +1 -0
- package/registry/password-input/files/src/components/ui/floating-input.tsx +33 -33
- package/registry/password-input/files/src/components/ui/password-input.tsx +29 -25
- package/registry/password-input/files/src/lib/kit.tsx +363 -11
- package/registry/password-input.json +1 -0
- package/registry/payment-card/files/src/components/ui/flip-card.tsx +6 -5
- package/registry/payment-card/files/src/components/ui/payment-card.tsx +17 -17
- package/registry/payment-card/files/src/components/ui/tilt-card.tsx +76 -91
- package/registry/payment-card/files/src/lib/kit.tsx +363 -11
- package/registry/payment-card.json +1 -0
- package/registry/paywall.json +1 -0
- package/registry/pixel-bar.json +1 -0
- package/registry/polar-area.json +1 -0
- package/registry/profile.json +1 -0
- package/registry/progress/files/src/components/ui/progress.tsx +29 -29
- package/registry/progress/files/src/lib/kit.tsx +363 -11
- package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +20 -20
- package/registry/progress-steps/files/src/lib/kit.tsx +363 -11
- package/registry/progress-steps.json +1 -0
- package/registry/progress.json +1 -0
- package/registry/qr-code-button.json +1 -0
- package/registry/radio-group/files/src/components/ui/radio-group.tsx +19 -19
- package/registry/radio-group/files/src/lib/kit.tsx +363 -11
- package/registry/radio-group.json +1 -0
- package/registry/rating.json +1 -0
- package/registry/ring-carousel.json +1 -0
- package/registry/ruler-time-picker/files/src/components/ui/ruler-time-picker.tsx +98 -82
- package/registry/ruler-time-picker/files/src/lib/kit.tsx +363 -11
- package/registry/ruler-time-picker.json +7 -0
- package/registry/scratch-card.json +1 -0
- package/registry/search-bar/files/src/components/ui/search-bar.tsx +25 -21
- package/registry/search-bar/files/src/lib/kit.tsx +363 -11
- package/registry/search-bar.json +1 -0
- package/registry/search-results.json +4 -0
- package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +8 -7
- package/registry/segmented-control/files/src/lib/kit.tsx +363 -11
- package/registry/segmented-control.json +1 -0
- package/registry/select/files/src/components/ui/select.tsx +93 -88
- package/registry/select/files/src/lib/kit.tsx +363 -11
- package/registry/select.json +6 -0
- package/registry/settings.json +1 -0
- package/registry/sign-in.json +1 -0
- package/registry/skeleton/files/src/components/ui/skeleton.tsx +149 -80
- package/registry/skeleton/files/src/lib/kit.tsx +363 -11
- package/registry/skeleton.json +1 -0
- package/registry/slide-to-confirm.json +1 -0
- package/registry/slider/files/src/components/ui/slider.tsx +103 -96
- package/registry/slider/files/src/lib/kit.tsx +363 -11
- package/registry/slider.json +5 -0
- package/registry/spin-wheel.json +1 -0
- package/registry/spinner/files/src/components/ui/spinner.tsx +39 -29
- package/registry/spinner/files/src/lib/kit.tsx +363 -11
- package/registry/spinner.json +6 -0
- package/registry/stateful-button/files/src/components/ui/stateful-button.tsx +39 -32
- package/registry/stateful-button/files/src/lib/kit.tsx +363 -11
- package/registry/stateful-button.json +5 -0
- package/registry/stepper/files/src/components/ui/stepper.tsx +38 -36
- package/registry/stepper/files/src/lib/kit.tsx +363 -11
- package/registry/stepper.json +1 -0
- package/registry/swipe-deck.json +1 -0
- package/registry/swipeable-row.json +4 -0
- package/registry/switch/files/src/components/ui/switch.tsx +39 -42
- package/registry/switch/files/src/lib/kit.tsx +363 -11
- package/registry/switch.json +1 -0
- package/registry/tabs/files/src/components/ui/tabs.tsx +59 -62
- package/registry/tabs/files/src/lib/kit.tsx +363 -11
- package/registry/tabs.json +1 -0
- package/registry/text-animation/files/src/components/ui/text-animation.tsx +55 -42
- package/registry/text-animation/files/src/lib/kit.tsx +363 -11
- package/registry/text-animation.json +7 -0
- package/registry/textarea/files/src/components/ui/textarea.tsx +10 -10
- package/registry/textarea/files/src/lib/kit.tsx +363 -11
- package/registry/textarea.json +1 -0
- package/registry/ticket-card.json +1 -0
- package/registry/ticket-shape/files/src/lib/kit.tsx +363 -11
- package/registry/ticket-shape/files/src/lib/ticket-shape.tsx +54 -44
- package/registry/ticket-shape.json +1 -0
- package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +76 -91
- package/registry/tilt-card/files/src/lib/kit.tsx +363 -11
- package/registry/tilt-card.json +1 -0
- package/registry/time-picker/files/src/components/ui/time-picker.tsx +122 -119
- package/registry/time-picker/files/src/lib/kit.tsx +363 -11
- package/registry/time-picker.json +1 -0
- package/registry/timeline/files/src/components/ui/avatar.tsx +84 -66
- package/registry/timeline/files/src/components/ui/timeline.tsx +44 -41
- package/registry/timeline/files/src/lib/kit.tsx +363 -11
- package/registry/timeline-chart.json +1 -0
- package/registry/timeline.json +1 -0
- package/registry/toast/files/src/components/ui/toast.tsx +541 -463
- package/registry/toast/files/src/lib/kit.tsx +363 -11
- package/registry/toast.json +7 -5
- package/registry/treemap.json +1 -0
- package/registry/waterfall.json +1 -0
- package/registry/wheel-list.json +1 -0
- package/schema/components.schema.json +1 -0
- package/registry/alert/files/src/components/ui/button.tsx +0 -290
- package/registry/confetti/files/src/lib/kit.tsx +0 -320
- package/registry/grain/files/src/lib/kit.tsx +0 -320
- package/registry/toast/files/src/components/ui/button.tsx +0 -290
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, useEffect, useId, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
1
|
+
import React, { createContext, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
AccessibilityInfo,
|
|
4
4
|
Animated,
|
|
@@ -18,23 +18,30 @@ import { alpha, motion, useKit } from '@/lib/kit';
|
|
|
18
18
|
export type SkeletonVariant = 'shimmer' | 'wave' | 'pulse' | 'static';
|
|
19
19
|
|
|
20
20
|
export interface SkeletonProps {
|
|
21
|
-
width?: DimensionValue;
|
|
22
|
-
|
|
21
|
+
width?: DimensionValue | undefined;
|
|
22
|
+
|
|
23
|
+
height?: DimensionValue | undefined;
|
|
24
|
+
|
|
23
25
|
/**
|
|
24
26
|
* Corner radius: a theme step, 'capsule' for bars that follow the kit radius (a pill at the
|
|
25
27
|
* default radius), 'full' for true pills / circles, or points.
|
|
26
28
|
*/
|
|
27
|
-
radius?: 'sm' | 'md' | 'lg' | 'xl' | 'capsule' | 'full' | number;
|
|
29
|
+
radius?: 'sm' | 'md' | 'lg' | 'xl' | 'capsule' | 'full' | number | undefined;
|
|
30
|
+
|
|
28
31
|
/**
|
|
29
32
|
* 'shimmer' sweeps one angled light band across every block on screen, 'wave' brightens blocks
|
|
30
33
|
* one after another from top to bottom, 'pulse' breathes, 'static' does nothing.
|
|
31
34
|
*/
|
|
32
|
-
variant?: SkeletonVariant;
|
|
35
|
+
variant?: SkeletonVariant | undefined;
|
|
36
|
+
|
|
33
37
|
/** Base colour of the block (default: a faint tint of the foreground). */
|
|
34
|
-
color?: string;
|
|
38
|
+
color?: string | undefined;
|
|
39
|
+
|
|
35
40
|
/** Centred overlay, e.g. a faint glyph (see `Skeleton.Media`). */
|
|
36
|
-
children?: React.ReactNode;
|
|
37
|
-
|
|
41
|
+
children?: React.ReactNode | undefined;
|
|
42
|
+
|
|
43
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
44
|
+
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
/* ------------------------------------------------------------------------------------------------
|
|
@@ -142,8 +149,10 @@ function measure(node: ComponentRef<typeof View> | null, e: LayoutChangeEvent, d
|
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
export interface SkeletonGroupProps {
|
|
145
|
-
children?: React.ReactNode;
|
|
146
|
-
|
|
152
|
+
children?: React.ReactNode | undefined;
|
|
153
|
+
|
|
154
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
155
|
+
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
/**
|
|
@@ -216,7 +225,7 @@ export function Skeleton({ width = '100%', height = 14, radius = 'sm', variant =
|
|
|
216
225
|
const local = (x: number) => start + (end - start) * easeSweep(x / SWEEP) - dy * TAN - dx - bw / 2;
|
|
217
226
|
const s = sample(local, 0, SWEEP, 24);
|
|
218
227
|
s.inputRange.push(1);
|
|
219
|
-
s.outputRange.push(s.outputRange[s.outputRange.length - 1]);
|
|
228
|
+
s.outputRange.push(s.outputRange[s.outputRange.length - 1] ?? 0);
|
|
220
229
|
return t.interpolate(s);
|
|
221
230
|
}, [mode, B, W, H, dx, dy, bw, t]);
|
|
222
231
|
|
|
@@ -301,14 +310,20 @@ export function Skeleton({ width = '100%', height = 14, radius = 'sm', variant =
|
|
|
301
310
|
|
|
302
311
|
export interface SkeletonTextProps {
|
|
303
312
|
/** Number of lines (default 3). */
|
|
304
|
-
lines?: number;
|
|
313
|
+
lines?: number | undefined;
|
|
314
|
+
|
|
305
315
|
/** Line height in points (default 12). */
|
|
306
|
-
lineHeight?: number;
|
|
307
|
-
|
|
316
|
+
lineHeight?: number | undefined;
|
|
317
|
+
|
|
318
|
+
gap?: number | undefined;
|
|
319
|
+
|
|
308
320
|
/** Width of the last line, so it reads like a paragraph (default '60%'). */
|
|
309
|
-
lastLineWidth?: DimensionValue;
|
|
310
|
-
|
|
311
|
-
|
|
321
|
+
lastLineWidth?: DimensionValue | undefined;
|
|
322
|
+
|
|
323
|
+
variant?: SkeletonVariant | undefined;
|
|
324
|
+
|
|
325
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
326
|
+
|
|
312
327
|
}
|
|
313
328
|
|
|
314
329
|
const RAGGED: DimensionValue[] = ['100%', '94%', '97%', '90%'];
|
|
@@ -331,10 +346,14 @@ export function SkeletonText({ lines = 3, lineHeight = 12, gap = 10, lastLineWid
|
|
|
331
346
|
}
|
|
332
347
|
|
|
333
348
|
export interface SkeletonAvatarProps {
|
|
334
|
-
size?: number;
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
349
|
+
size?: number | undefined;
|
|
350
|
+
|
|
351
|
+
shape?: 'circle' | 'rounded' | undefined;
|
|
352
|
+
|
|
353
|
+
variant?: SkeletonVariant | undefined;
|
|
354
|
+
|
|
355
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
356
|
+
|
|
338
357
|
}
|
|
339
358
|
|
|
340
359
|
/** Round (or rounded-square) avatar placeholder. */
|
|
@@ -353,17 +372,25 @@ export function SkeletonAvatar({ size = 40, shape = 'circle', variant, style }:
|
|
|
353
372
|
|
|
354
373
|
export interface SkeletonMediaProps {
|
|
355
374
|
/** Width / height ratio (default 16 / 9). Ignored when `height` is set. */
|
|
356
|
-
aspectRatio?: number;
|
|
375
|
+
aspectRatio?: number | undefined;
|
|
376
|
+
|
|
357
377
|
/** Fixed height in points. */
|
|
358
|
-
height?: number;
|
|
359
|
-
|
|
378
|
+
height?: number | undefined;
|
|
379
|
+
|
|
380
|
+
width?: DimensionValue | undefined;
|
|
381
|
+
|
|
360
382
|
/** Draw a faint image glyph in the centre (default false). */
|
|
361
|
-
glyph?: boolean;
|
|
383
|
+
glyph?: boolean | undefined;
|
|
384
|
+
|
|
362
385
|
/** Glyph size in points (default 28). */
|
|
363
|
-
glyphSize?: number;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
386
|
+
glyphSize?: number | undefined;
|
|
387
|
+
|
|
388
|
+
radius?: SkeletonProps['radius'] | undefined;
|
|
389
|
+
|
|
390
|
+
variant?: SkeletonVariant | undefined;
|
|
391
|
+
|
|
392
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
393
|
+
|
|
367
394
|
}
|
|
368
395
|
|
|
369
396
|
/** Image / video placeholder (optionally with a faint picture glyph in the middle). */
|
|
@@ -404,16 +431,23 @@ export function SkeletonMedia({
|
|
|
404
431
|
|
|
405
432
|
export interface SkeletonListProps {
|
|
406
433
|
/** Number of rows (default 4). */
|
|
407
|
-
rows?: number;
|
|
434
|
+
rows?: number | undefined;
|
|
435
|
+
|
|
408
436
|
/** Avatar size (default 44). 0 hides it. */
|
|
409
|
-
avatarSize?: number;
|
|
410
|
-
|
|
437
|
+
avatarSize?: number | undefined;
|
|
438
|
+
|
|
439
|
+
avatarShape?: 'circle' | 'rounded' | undefined;
|
|
440
|
+
|
|
411
441
|
/** Trailing short bar, like a time stamp or price (default true). */
|
|
412
|
-
trailing?: boolean;
|
|
442
|
+
trailing?: boolean | undefined;
|
|
443
|
+
|
|
413
444
|
/** Hairline between rows (default false). */
|
|
414
|
-
dividers?: boolean;
|
|
415
|
-
|
|
416
|
-
|
|
445
|
+
dividers?: boolean | undefined;
|
|
446
|
+
|
|
447
|
+
variant?: SkeletonVariant | undefined;
|
|
448
|
+
|
|
449
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
450
|
+
|
|
417
451
|
}
|
|
418
452
|
|
|
419
453
|
const TITLE_W: DimensionValue[] = ['58%', '44%', '66%', '50%', '62%'];
|
|
@@ -458,16 +492,23 @@ export function SkeletonList({
|
|
|
458
492
|
|
|
459
493
|
export interface SkeletonCardProps {
|
|
460
494
|
/** Show the media block (default true). */
|
|
461
|
-
media?: boolean;
|
|
462
|
-
|
|
495
|
+
media?: boolean | undefined;
|
|
496
|
+
|
|
497
|
+
mediaHeight?: number | undefined;
|
|
498
|
+
|
|
463
499
|
/** Show the author row: avatar, name, handle · time, overflow menu (default true). */
|
|
464
|
-
header?: boolean;
|
|
500
|
+
header?: boolean | undefined;
|
|
501
|
+
|
|
465
502
|
/** Body text lines (default 2). */
|
|
466
|
-
lines?: number;
|
|
503
|
+
lines?: number | undefined;
|
|
504
|
+
|
|
467
505
|
/** Like / comment / share row along the bottom (default true). */
|
|
468
|
-
actions?: boolean;
|
|
469
|
-
|
|
470
|
-
|
|
506
|
+
actions?: boolean | undefined;
|
|
507
|
+
|
|
508
|
+
variant?: SkeletonVariant | undefined;
|
|
509
|
+
|
|
510
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
511
|
+
|
|
471
512
|
}
|
|
472
513
|
|
|
473
514
|
/** A feed post placeholder: author row, caption, media and an action bar — borderless, like the content it stands in for. */
|
|
@@ -511,21 +552,30 @@ export function SkeletonCard({
|
|
|
511
552
|
|
|
512
553
|
export interface SkeletonNavProps {
|
|
513
554
|
/** App bar: back + title + trailing actions (default true). */
|
|
514
|
-
header?: boolean;
|
|
555
|
+
header?: boolean | undefined;
|
|
556
|
+
|
|
515
557
|
/** Show a back chevron placeholder (default true when header is on). */
|
|
516
|
-
back?: boolean;
|
|
558
|
+
back?: boolean | undefined;
|
|
559
|
+
|
|
517
560
|
/** Trailing action pills in the header (default 2). */
|
|
518
|
-
actions?: number;
|
|
561
|
+
actions?: number | undefined;
|
|
562
|
+
|
|
519
563
|
/** Bottom tab bar (default true). */
|
|
520
|
-
tabs?: boolean;
|
|
564
|
+
tabs?: boolean | undefined;
|
|
565
|
+
|
|
521
566
|
/** Number of bottom tabs (default 4). */
|
|
522
|
-
tabCount?: number;
|
|
567
|
+
tabCount?: number | undefined;
|
|
568
|
+
|
|
523
569
|
/** Body: how many list rows to show while content loads (default 4). 0 = empty body. */
|
|
524
|
-
rows?: number;
|
|
570
|
+
rows?: number | undefined;
|
|
571
|
+
|
|
525
572
|
/** Custom body instead of the default list rows. */
|
|
526
|
-
children?: React.ReactNode;
|
|
527
|
-
|
|
528
|
-
|
|
573
|
+
children?: React.ReactNode | undefined;
|
|
574
|
+
|
|
575
|
+
variant?: SkeletonVariant | undefined;
|
|
576
|
+
|
|
577
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
578
|
+
|
|
529
579
|
}
|
|
530
580
|
|
|
531
581
|
/**
|
|
@@ -586,16 +636,22 @@ export interface SkeletonRevealProps {
|
|
|
586
636
|
/** While true the skeleton shows; flip to false when the data arrives. */
|
|
587
637
|
loading: boolean;
|
|
588
638
|
/** Placeholder shown while loading (default: three text lines). */
|
|
589
|
-
skeleton?: React.ReactNode;
|
|
639
|
+
skeleton?: React.ReactNode | undefined;
|
|
640
|
+
|
|
590
641
|
/** The real content. Top-level children rise in one after another. */
|
|
591
|
-
children?: React.ReactNode;
|
|
642
|
+
children?: React.ReactNode | undefined;
|
|
643
|
+
|
|
592
644
|
/** Delay between each top-level child rising in, in ms (default 70). 0 reveals it as one block. */
|
|
593
|
-
stagger?: number;
|
|
645
|
+
stagger?: number | undefined;
|
|
646
|
+
|
|
594
647
|
/** Glide the container height from the skeleton's height to the content's (default true). */
|
|
595
|
-
animateHeight?: boolean;
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
648
|
+
animateHeight?: boolean | undefined;
|
|
649
|
+
|
|
650
|
+
/** Screen reader label while loading (default: the kit's `labels.loading`). */
|
|
651
|
+
loadingLabel?: string | undefined;
|
|
652
|
+
|
|
653
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
654
|
+
|
|
599
655
|
}
|
|
600
656
|
|
|
601
657
|
type Layer = 'skeleton' | 'content';
|
|
@@ -615,9 +671,10 @@ export function SkeletonReveal({
|
|
|
615
671
|
children,
|
|
616
672
|
stagger = 70,
|
|
617
673
|
animateHeight = true,
|
|
618
|
-
loadingLabel
|
|
674
|
+
loadingLabel,
|
|
619
675
|
style,
|
|
620
676
|
}: SkeletonRevealProps) {
|
|
677
|
+
const { labels } = useKit();
|
|
621
678
|
const reduce = useReduceMotion();
|
|
622
679
|
const [mode, setMode] = useState<Layer>(loading ? 'skeleton' : 'content');
|
|
623
680
|
const [leaving, setLeaving] = useState<Layer | null>(null);
|
|
@@ -625,9 +682,9 @@ export function SkeletonReveal({
|
|
|
625
682
|
const heights = useRef<Record<Layer, number>>({ skeleton: 0, content: 0 });
|
|
626
683
|
const pending = useRef(false);
|
|
627
684
|
const token = useRef(0);
|
|
628
|
-
const h =
|
|
629
|
-
const skA =
|
|
630
|
-
const ctA =
|
|
685
|
+
const [h] = useState(() => new Animated.Value(0)); // JS driver: container height
|
|
686
|
+
const [skA] = useState(() => new Animated.Value(loading ? 1 : 0)); // native: skeleton layer
|
|
687
|
+
const [ctA] = useState(() => new Animated.Value(loading ? 0 : 1)); // native: content layer
|
|
631
688
|
|
|
632
689
|
const items = React.Children.toArray(children);
|
|
633
690
|
const staggered = stagger > 0 && items.length > 1;
|
|
@@ -658,37 +715,49 @@ export function SkeletonReveal({
|
|
|
658
715
|
});
|
|
659
716
|
};
|
|
660
717
|
|
|
661
|
-
|
|
718
|
+
// `loading` flipped: swap layers while rendering, then start the animation in a layout effect so the
|
|
719
|
+
// held height and the new layer's starting opacity are set before that frame paints.
|
|
720
|
+
const [loadingSeen, setLoadingSeen] = useState(loading);
|
|
721
|
+
const [turn, setTurn] = useState<{ next: Layer; prev: Layer; holdHeight: boolean; ready: boolean } | null>(null);
|
|
722
|
+
if (loading !== loadingSeen) {
|
|
723
|
+
setLoadingSeen(loading);
|
|
662
724
|
const next: Layer = loading ? 'skeleton' : 'content';
|
|
663
|
-
if (next
|
|
664
|
-
|
|
725
|
+
if (next !== mode) {
|
|
726
|
+
if (reduce) {
|
|
727
|
+
setFixed(false);
|
|
728
|
+
setLeaving(null);
|
|
729
|
+
} else {
|
|
730
|
+
if (animateHeight) setFixed(true);
|
|
731
|
+
setLeaving(mode);
|
|
732
|
+
}
|
|
733
|
+
setTurn({ next, prev: mode, holdHeight: animateHeight && !fixed, ready: leaving === next });
|
|
734
|
+
setMode(next);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
useLayoutEffect(() => {
|
|
739
|
+
if (!turn) return;
|
|
740
|
+
const { next, prev } = turn;
|
|
665
741
|
if (reduce) {
|
|
666
742
|
token.current += 1;
|
|
667
743
|
value(prev).setValue(0);
|
|
668
744
|
value(next).setValue(1);
|
|
669
|
-
setFixed(false);
|
|
670
|
-
setLeaving(null);
|
|
671
|
-
setMode(next);
|
|
672
745
|
return;
|
|
673
746
|
}
|
|
674
747
|
if (animateHeight) {
|
|
675
748
|
h.stopAnimation();
|
|
676
|
-
if (
|
|
677
|
-
setFixed(true);
|
|
749
|
+
if (turn.holdHeight) h.setValue(heights.current[prev]);
|
|
678
750
|
}
|
|
679
|
-
|
|
680
|
-
setLeaving(prev);
|
|
681
|
-
setMode(next);
|
|
682
|
-
if (wasMounted && heights.current[next] > 0) {
|
|
751
|
+
if (turn.ready && heights.current[next] > 0) {
|
|
683
752
|
run(next, prev);
|
|
684
753
|
} else {
|
|
685
754
|
value(next).setValue(0);
|
|
686
755
|
pending.current = true;
|
|
687
756
|
}
|
|
688
757
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
689
|
-
}, [
|
|
758
|
+
}, [turn]);
|
|
690
759
|
|
|
691
|
-
const
|
|
760
|
+
const measure = (l: Layer, e: LayoutChangeEvent) => {
|
|
692
761
|
heights.current[l] = e.nativeEvent.layout.height;
|
|
693
762
|
if (l === mode && pending.current) {
|
|
694
763
|
pending.current = false;
|
|
@@ -726,9 +795,9 @@ export function SkeletonReveal({
|
|
|
726
795
|
<Animated.View
|
|
727
796
|
accessible={mode === 'skeleton'}
|
|
728
797
|
accessibilityRole="progressbar"
|
|
729
|
-
accessibilityLabel={loadingLabel}
|
|
798
|
+
accessibilityLabel={loadingLabel ?? labels.loading}
|
|
730
799
|
pointerEvents="none"
|
|
731
|
-
onLayout={
|
|
800
|
+
onLayout={(e) => measure('skeleton', e)}
|
|
732
801
|
style={[layerStyle('skeleton'), { opacity: skA }]}
|
|
733
802
|
>
|
|
734
803
|
<SkeletonGroup>{skeleton ?? <SkeletonText lines={3} />}</SkeletonGroup>
|
|
@@ -738,7 +807,7 @@ export function SkeletonReveal({
|
|
|
738
807
|
<Animated.View
|
|
739
808
|
accessibilityLiveRegion="polite"
|
|
740
809
|
pointerEvents={mode === 'content' ? 'auto' : 'none'}
|
|
741
|
-
onLayout={
|
|
810
|
+
onLayout={(e) => measure('content', e)}
|
|
742
811
|
style={[layerStyle('content'), staggered ? null : rise(0)]}
|
|
743
812
|
>
|
|
744
813
|
{staggered
|