@expokit/cli 0.4.3 → 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 +313 -4
- 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/flip-calendar.json +106 -0
- 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/paywall.json +144 -0
- 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/ruler-time-picker.json +147 -0
- 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 +462 -12
- package/registry/accordion.json +1 -0
- package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +50 -58
- package/registry/action-sheet/files/src/lib/kit.tsx +462 -12
- package/registry/action-sheet.json +1 -0
- package/registry/alert/files/src/components/ui/alert.tsx +20 -13
- package/registry/alert/files/src/lib/kit.tsx +462 -12
- package/registry/alert.json +3 -4
- package/registry/assistant-app.json +1 -0
- package/registry/avatar/files/src/components/ui/avatar.tsx +89 -74
- package/registry/avatar/files/src/lib/kit.tsx +462 -12
- package/registry/avatar.json +1 -0
- package/registry/badge/files/src/components/ui/badge.tsx +36 -36
- package/registry/badge/files/src/lib/kit.tsx +462 -12
- package/registry/badge.json +1 -0
- package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +39 -44
- package/registry/bottom-nav/files/src/lib/kit.tsx +462 -12
- package/registry/bottom-nav.json +5 -0
- package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +357 -300
- package/registry/bottom-sheet/files/src/lib/kit.tsx +462 -12
- package/registry/bottom-sheet.json +5 -1
- package/registry/bullet.json +1 -0
- package/registry/button/files/src/components/ui/button.tsx +23 -34
- package/registry/button/files/src/lib/kit.tsx +462 -12
- package/registry/button-3d/files/src/components/ui/button-3d.tsx +6 -9
- package/registry/button-3d/files/src/lib/kit.tsx +462 -12
- package/registry/button-3d.json +1 -0
- package/registry/button.json +1 -0
- package/registry/calendar/files/src/components/ui/calendar.tsx +77 -79
- package/registry/calendar/files/src/lib/kit.tsx +462 -12
- package/registry/calendar.json +1 -0
- package/registry/card/files/src/components/ui/card.tsx +7 -6
- package/registry/card/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- package/registry/checkbox.json +1 -0
- package/registry/checkout.json +1 -0
- package/registry/chip-group/files/src/components/ui/chip-group.tsx +24 -24
- package/registry/chip-group/files/src/lib/kit.tsx +462 -12
- 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 +47 -52
- package/registry/coupon/files/src/components/ui/flip-card.tsx +9 -14
- package/registry/coupon/files/src/components/ui/tilt-card.tsx +80 -101
- package/registry/coupon/files/src/lib/kit.tsx +462 -12
- 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 +77 -79
- package/registry/date-picker/files/src/components/ui/date-picker.tsx +64 -71
- package/registry/date-picker/files/src/lib/kit.tsx +462 -12
- package/registry/date-picker.json +1 -0
- package/registry/dialog/files/src/components/ui/dialog.tsx +66 -68
- package/registry/dialog/files/src/lib/kit.tsx +462 -12
- package/registry/dialog.json +1 -0
- package/registry/donut-shop.json +1 -0
- package/registry/drawer/files/src/components/ui/drawer.tsx +76 -88
- package/registry/drawer/files/src/lib/kit.tsx +462 -12
- 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 +632 -0
- package/registry/flip-calendar/files/src/lib/kit.tsx +672 -0
- package/registry/flip-calendar.json +24 -0
- package/registry/flip-card/files/src/components/ui/flip-card.tsx +9 -14
- package/registry/flip-card/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- 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 +462 -12
- 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 +29 -16
- package/registry/liquidglass-tab/files/src/components/TabScreen.tsx +33 -19
- 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 +43 -43
- package/registry/list-item/files/src/lib/kit.tsx +462 -12
- 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 +49 -30
- package/registry/otp-input/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- package/registry/password-input.json +1 -0
- package/registry/payment-card/files/src/components/ui/flip-card.tsx +9 -14
- package/registry/payment-card/files/src/components/ui/payment-card.tsx +26 -20
- package/registry/payment-card/files/src/components/ui/tilt-card.tsx +80 -101
- package/registry/payment-card/files/src/lib/kit.tsx +462 -12
- package/registry/payment-card.json +1 -0
- package/registry/paywall.json +23 -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 +31 -29
- package/registry/progress/files/src/lib/kit.tsx +462 -12
- package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +21 -21
- package/registry/progress-steps/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- 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 +832 -0
- package/registry/ruler-time-picker/files/src/lib/kit.tsx +672 -0
- package/registry/ruler-time-picker.json +26 -0
- package/registry/scratch-card.json +1 -0
- package/registry/search-bar/files/src/components/ui/search-bar.tsx +28 -28
- package/registry/search-bar/files/src/lib/kit.tsx +462 -12
- 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 +11 -17
- package/registry/segmented-control/files/src/lib/kit.tsx +462 -12
- package/registry/segmented-control.json +1 -0
- package/registry/select/files/src/components/ui/select.tsx +107 -104
- package/registry/select/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- package/registry/skeleton.json +1 -0
- package/registry/slide-to-confirm.json +1 -0
- package/registry/slider/files/src/components/ui/slider.tsx +106 -108
- package/registry/slider/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- 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 +462 -12
- package/registry/stateful-button.json +5 -0
- package/registry/stepper/files/src/components/ui/stepper.tsx +40 -38
- package/registry/stepper/files/src/lib/kit.tsx +462 -12
- 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 +41 -47
- package/registry/switch/files/src/lib/kit.tsx +462 -12
- package/registry/switch.json +1 -0
- package/registry/tabs/files/src/components/ui/tabs.tsx +61 -64
- package/registry/tabs/files/src/lib/kit.tsx +462 -12
- 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 +462 -12
- 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 +462 -12
- package/registry/textarea.json +1 -0
- package/registry/ticket-card.json +1 -0
- package/registry/ticket-shape/files/src/lib/kit.tsx +462 -12
- 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 +80 -101
- package/registry/tilt-card/files/src/lib/kit.tsx +462 -12
- package/registry/tilt-card.json +1 -0
- package/registry/time-picker/files/src/components/ui/time-picker.tsx +136 -131
- package/registry/time-picker/files/src/lib/kit.tsx +462 -12
- package/registry/time-picker.json +1 -0
- package/registry/timeline/files/src/components/ui/avatar.tsx +89 -74
- package/registry/timeline/files/src/components/ui/timeline.tsx +49 -57
- package/registry/timeline/files/src/lib/kit.tsx +462 -12
- package/registry/timeline-chart.json +1 -0
- package/registry/timeline.json +1 -0
- package/registry/toast/files/src/components/ui/toast.tsx +543 -465
- package/registry/toast/files/src/lib/kit.tsx +462 -12
- 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 -303
- package/registry/confetti/files/src/lib/kit.tsx +0 -222
- package/registry/grain/files/src/lib/kit.tsx +0 -222
- package/registry/toast/files/src/components/ui/button.tsx +0 -303
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "paywall",
|
|
3
|
+
"category": "Blocks",
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"exportName": "Paywall",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/components/blocks/paywall.tsx"
|
|
8
|
+
],
|
|
9
|
+
"summary": "Animated paywall, free-trial timeline, success and win-back screens.",
|
|
10
|
+
"props": [
|
|
11
|
+
[
|
|
12
|
+
"variant",
|
|
13
|
+
"\"card\" | \"glow\" | \"trial\"",
|
|
14
|
+
"\"card\"",
|
|
15
|
+
"Gradient card + plan picker, dark full-bleed with an annual toggle, or how the free trial works."
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
"appName",
|
|
19
|
+
"string",
|
|
20
|
+
"'Lumen'",
|
|
21
|
+
"Shown on the card and the glow pill."
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
"title",
|
|
25
|
+
"string",
|
|
26
|
+
"per variant",
|
|
27
|
+
"Heading."
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"subtitle",
|
|
31
|
+
"string",
|
|
32
|
+
"per variant",
|
|
33
|
+
"Line under the heading."
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"features",
|
|
37
|
+
"{ title, icon? }[]",
|
|
38
|
+
"per variant",
|
|
39
|
+
"Feature grid (card) or pills (glow)."
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"plans",
|
|
43
|
+
"PaywallPlan[]",
|
|
44
|
+
"yearly / monthly / lifetime",
|
|
45
|
+
"{ id, label, price, period, caption?, badge?, trialDays?, cta? }. In glow the toggle picks plans[0] (on) or plans[1] (off)."
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"plan",
|
|
49
|
+
"string",
|
|
50
|
+
"—",
|
|
51
|
+
"Selected plan id (controlled)."
|
|
52
|
+
],
|
|
53
|
+
[
|
|
54
|
+
"defaultPlan",
|
|
55
|
+
"string",
|
|
56
|
+
"plans[0].id",
|
|
57
|
+
"Initial plan when uncontrolled."
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
"onPlanChange",
|
|
61
|
+
"(id: string) => void",
|
|
62
|
+
"—",
|
|
63
|
+
"A plan was picked."
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
"onPurchase",
|
|
67
|
+
"(plan: PaywallPlan) => void",
|
|
68
|
+
"—",
|
|
69
|
+
"Pressed the main button."
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
"onRestore",
|
|
73
|
+
"() => void",
|
|
74
|
+
"—",
|
|
75
|
+
"Shows “Restore” in the top-left corner."
|
|
76
|
+
],
|
|
77
|
+
[
|
|
78
|
+
"onClose",
|
|
79
|
+
"() => void",
|
|
80
|
+
"—",
|
|
81
|
+
"Shows a close button."
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
"reminder",
|
|
85
|
+
"boolean",
|
|
86
|
+
"true",
|
|
87
|
+
"trial: the “remind me” switch (controlled with onReminderChange)."
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"auroraColors",
|
|
91
|
+
"[string, string, string]",
|
|
92
|
+
"orange, violet, cyan",
|
|
93
|
+
"Colours of the moving aurora."
|
|
94
|
+
],
|
|
95
|
+
[
|
|
96
|
+
"accent",
|
|
97
|
+
"string",
|
|
98
|
+
"theme accent",
|
|
99
|
+
"Button and selected-plan colour."
|
|
100
|
+
],
|
|
101
|
+
[
|
|
102
|
+
"topInset",
|
|
103
|
+
"number",
|
|
104
|
+
"0",
|
|
105
|
+
"Space above the restore / close buttons, e.g. useSafeAreaInsets().top. Also on PaywallSuccess and PaywallWinback."
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
"bottomInset",
|
|
109
|
+
"number",
|
|
110
|
+
"30 on iOS, 16 elsewhere",
|
|
111
|
+
"Space under the button, e.g. useSafeAreaInsets().bottom + 12."
|
|
112
|
+
],
|
|
113
|
+
[
|
|
114
|
+
"style",
|
|
115
|
+
"StyleProp<ViewStyle>",
|
|
116
|
+
"—",
|
|
117
|
+
"Root style."
|
|
118
|
+
]
|
|
119
|
+
],
|
|
120
|
+
"behavior": [
|
|
121
|
+
[
|
|
122
|
+
"Motion",
|
|
123
|
+
"The aurora drifts on three loops of different lengths, a sheen sweeps the card, rows rise in one after another and prices slide when the plan changes. Springs are critically damped — nothing bounces."
|
|
124
|
+
],
|
|
125
|
+
[
|
|
126
|
+
"Touch",
|
|
127
|
+
"Drag the card to tilt it; it springs flat when you let go. Plan tiles and rows scale down slightly on press."
|
|
128
|
+
],
|
|
129
|
+
[
|
|
130
|
+
"Reduced motion",
|
|
131
|
+
"Loops, tilt, lifts and press scaling are off; fades and colour changes stay. Confetti fires fewer pieces."
|
|
132
|
+
],
|
|
133
|
+
[
|
|
134
|
+
"Screen readers",
|
|
135
|
+
"Plans and reasons are radio groups and the card reads as one label."
|
|
136
|
+
],
|
|
137
|
+
[
|
|
138
|
+
"Layout",
|
|
139
|
+
"Restore sits top-left and close top-right, clear of the button. The button bar stays pinned and content fades out under it. Pass topInset / bottomInset (e.g. from useSafeAreaInsets) for the notch and home indicator."
|
|
140
|
+
]
|
|
141
|
+
],
|
|
142
|
+
"usage": null,
|
|
143
|
+
"examples": []
|
|
144
|
+
}
|
|
@@ -67,6 +67,12 @@
|
|
|
67
67
|
"string",
|
|
68
68
|
"auto summary",
|
|
69
69
|
"What screen readers announce; defaults to a summary of the data."
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
"accessibilityHint",
|
|
73
|
+
"string",
|
|
74
|
+
"\"Swipe up or down to read each …\"",
|
|
75
|
+
"Screen-reader hint for the swipe-to-read gesture; pass your own to translate it."
|
|
70
76
|
]
|
|
71
77
|
],
|
|
72
78
|
"behavior": [],
|
|
@@ -79,6 +79,12 @@
|
|
|
79
79
|
"string",
|
|
80
80
|
"auto summary",
|
|
81
81
|
"What screen readers announce; defaults to a summary of the data."
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
"accessibilityHint",
|
|
85
|
+
"string",
|
|
86
|
+
"\"Swipe up or down to read each …\"",
|
|
87
|
+
"Screen-reader hint for the swipe-to-read gesture; pass your own to translate it."
|
|
82
88
|
]
|
|
83
89
|
],
|
|
84
90
|
"behavior": [],
|
|
@@ -17,21 +17,27 @@
|
|
|
17
17
|
[
|
|
18
18
|
"label",
|
|
19
19
|
"string",
|
|
20
|
-
"
|
|
20
|
+
"labels.showQrCode",
|
|
21
21
|
"Text on the pill."
|
|
22
22
|
],
|
|
23
23
|
[
|
|
24
24
|
"copyLabel",
|
|
25
25
|
"string",
|
|
26
|
-
"
|
|
26
|
+
"labels.copy",
|
|
27
27
|
"Copy button text."
|
|
28
28
|
],
|
|
29
29
|
[
|
|
30
30
|
"copiedLabel",
|
|
31
31
|
"string",
|
|
32
|
-
"
|
|
32
|
+
"labels.copied",
|
|
33
33
|
"Shown after Copy is pressed."
|
|
34
34
|
],
|
|
35
|
+
[
|
|
36
|
+
"closeLabel",
|
|
37
|
+
"string",
|
|
38
|
+
"labels.close",
|
|
39
|
+
"Screen-reader name of the card's close button. Set it app-wide with KitProvider's labels."
|
|
40
|
+
],
|
|
35
41
|
[
|
|
36
42
|
"onCopy",
|
|
37
43
|
"(value: string) => void",
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ruler-time-picker",
|
|
3
|
+
"category": "Inputs",
|
|
4
|
+
"aliases": [
|
|
5
|
+
"scrub-time-picker",
|
|
6
|
+
"drag-time-picker",
|
|
7
|
+
"ruler-date-picker",
|
|
8
|
+
"scrub-date-picker",
|
|
9
|
+
"day-ruler"
|
|
10
|
+
],
|
|
11
|
+
"exportName": "RulerTimePicker",
|
|
12
|
+
"files": [
|
|
13
|
+
"src/components/ui/ruler-time-picker.tsx"
|
|
14
|
+
],
|
|
15
|
+
"summary": "Drag a tick ruler and the big time or date rolls piece by piece with a motion blur.",
|
|
16
|
+
"props": [
|
|
17
|
+
[
|
|
18
|
+
"mode",
|
|
19
|
+
"'time' | 'date'",
|
|
20
|
+
"'time'",
|
|
21
|
+
"One tick per `step` minutes, or one tick per day with the 1st of each month marked."
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
"value",
|
|
25
|
+
"{ hours, minutes } | Date",
|
|
26
|
+
"—",
|
|
27
|
+
"Controlled value: a 24-hour time, or a Date in date mode (its time of day is kept)."
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"defaultValue",
|
|
31
|
+
"{ hours, minutes } | Date",
|
|
32
|
+
"09:00 · today",
|
|
33
|
+
"Initial value when uncontrolled."
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"onChange",
|
|
37
|
+
"(value) => void",
|
|
38
|
+
"—",
|
|
39
|
+
"Called on every tick the ruler passes, while you drag."
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"label",
|
|
43
|
+
"string",
|
|
44
|
+
"—",
|
|
45
|
+
"Small line above the value, e.g. 'Reminder time:'."
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"step",
|
|
49
|
+
"number",
|
|
50
|
+
"5",
|
|
51
|
+
"Time: minutes per tick (1–60)."
|
|
52
|
+
],
|
|
53
|
+
[
|
|
54
|
+
"hour12",
|
|
55
|
+
"boolean",
|
|
56
|
+
"true",
|
|
57
|
+
"Time: 12-hour clock with a rolling am / pm; false for 00–23."
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
"minDate / maxDate",
|
|
61
|
+
"Date",
|
|
62
|
+
"—",
|
|
63
|
+
"Date: earliest / latest pickable day; the ruler resists past them."
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
"showYear",
|
|
67
|
+
"'auto' | 'always' | 'never'",
|
|
68
|
+
"'auto'",
|
|
69
|
+
"Date: 'auto' shows the year only when it isn't this year."
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
"locale",
|
|
73
|
+
"string",
|
|
74
|
+
"device",
|
|
75
|
+
"Date: weekday and month names (Intl), English where Intl isn't available."
|
|
76
|
+
],
|
|
77
|
+
[
|
|
78
|
+
"size",
|
|
79
|
+
"'sm' | 'md' | 'lg'",
|
|
80
|
+
"'md'",
|
|
81
|
+
"Time at 40 / 52 / 64pt, date at 34 / 44 / 54pt."
|
|
82
|
+
],
|
|
83
|
+
[
|
|
84
|
+
"accent",
|
|
85
|
+
"string",
|
|
86
|
+
"theme accent",
|
|
87
|
+
"Centre needle colour."
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"haptics",
|
|
91
|
+
"boolean",
|
|
92
|
+
"true",
|
|
93
|
+
"A light tap on every step, a firmer one on each whole hour (time) or new month (date)."
|
|
94
|
+
],
|
|
95
|
+
[
|
|
96
|
+
"sound",
|
|
97
|
+
"boolean",
|
|
98
|
+
"true",
|
|
99
|
+
"A soft tick on every step, generated in code (no audio file); it plays alongside other audio."
|
|
100
|
+
],
|
|
101
|
+
[
|
|
102
|
+
"accessibilityLabel",
|
|
103
|
+
"string",
|
|
104
|
+
"label",
|
|
105
|
+
"Name read by screen readers."
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
"style",
|
|
109
|
+
"StyleProp<ViewStyle>",
|
|
110
|
+
"—",
|
|
111
|
+
"Root container."
|
|
112
|
+
],
|
|
113
|
+
[
|
|
114
|
+
"textStyle",
|
|
115
|
+
"StyleProp<TextStyle>",
|
|
116
|
+
"—",
|
|
117
|
+
"The big value text (colour, weight, font family)."
|
|
118
|
+
]
|
|
119
|
+
],
|
|
120
|
+
"behavior": [
|
|
121
|
+
[
|
|
122
|
+
"Touch",
|
|
123
|
+
"Drag sideways anywhere on the picker to scrub; fling to coast. It snaps to the nearest step when it stops. A touch during a fling catches it. In date mode, past minDate / maxDate the ruler follows at a fraction of your finger and springs back. Every step taps (firmer on the hour or a new month) and ticks softly."
|
|
124
|
+
],
|
|
125
|
+
[
|
|
126
|
+
"Motion",
|
|
127
|
+
"Ticks (and month markers) slide, swell and fade on the native driver from one endless pool. Each piece that changes rolls up (later) or down (earlier) with ghosted copies for a motion blur. Reduce Motion swaps the roll for an instant change."
|
|
128
|
+
],
|
|
129
|
+
[
|
|
130
|
+
"Screen readers",
|
|
131
|
+
"One adjustable element whose value is the spoken time or full date; increment / decrement move one step, within the limits."
|
|
132
|
+
]
|
|
133
|
+
],
|
|
134
|
+
"usage": "import { useState } from 'react';\nimport { RulerTimePicker, type TimeValue } from '@/components/ui/ruler-time-picker';\n\nconst [time, setTime] = useState<TimeValue>({ hours: 2, minutes: 15 });\n<RulerTimePicker label=\"Reminder time:\" value={time} onChange={setTime} />\n\n// One tick per day\nconst [date, setDate] = useState(new Date());\n<RulerTimePicker mode=\"date\" label=\"Delivery date:\" value={date} onChange={setDate} minDate={new Date()} />",
|
|
135
|
+
"examples": [
|
|
136
|
+
{
|
|
137
|
+
"name": "Reminder",
|
|
138
|
+
"title": "Reminder",
|
|
139
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { RulerTimePicker, type TimeValue } from '@/components/ui/ruler-time-picker';\nimport { alpha, useKit } from '@/lib/kit';\n\n/** Controls stop at iOS's largest standard text size; content text stays uncapped. */\nconst FONT_CAP = 1.35;\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\nconst BLUR: [number, number][] = [2, 4, 7, 10].flatMap((r, ring) =>\n Array.from({ length: 8 }, (_, i): [number, number] => {\n const a = ((i + ring / 2) / 8) * Math.PI * 2;\n return [Math.cos(a) * r, Math.sin(a) * r];\n }),\n);\n\n/** The settings screen the sheet was opened from, as blocks: a title, a grouped list and toggles. */\nconst SettingsScreen = React.memo(function SettingsScreen() {\n const { colors, radius, dark } = useKit();\n // In dark mode the grouped rows sit a step lighter than the screen, like iOS Settings.\n const group = dark ? colors.secondary : colors.card;\n const rows: [number, 'value' | 'on' | 'off'][] = [\n [0.42, 'value'],\n [0.3, 'value'],\n [0.38, 'on'],\n [0.34, 'on'],\n [0.4, 'off'],\n [0.28, 'value'],\n ];\n const bar = (w: number | `${number}%`, h: number, color: string) => (\n <View style={{ width: w, height: h, backgroundColor: color, borderRadius: radius.capsule(h) }} />\n );\n return (\n <View style={s.screen}>\n {bar(150, 30, alpha(colors.foreground, 0.7))}\n <View style={[s.group, { backgroundColor: group, borderRadius: radius.lg }]}>\n {rows.map(([w, kind], i) => (\n <View key={i} style={[s.row, i > 0 && { borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: colors.border }]}>\n {bar(`${w * 100}%`, 14, alpha(colors.foreground, 0.45))}\n {kind === 'value' ? (\n bar(64, 14, colors.mutedForeground)\n ) : (\n <View style={[s.toggle, { backgroundColor: kind === 'on' ? colors.accent : colors.border, borderRadius: radius.capsule(28) }]}>\n <View style={[s.knob, { backgroundColor: colors.background, alignSelf: kind === 'on' ? 'flex-end' : 'flex-start', borderRadius: radius.capsule(24) }]} />\n </View>\n )}\n </View>\n ))}\n </View>\n <View style={[s.group, s.card2, { backgroundColor: group, borderRadius: radius.lg }]}>\n {bar('55%', 14, alpha(colors.foreground, 0.45))}\n {bar('80%', 12, colors.mutedForeground)}\n </View>\n </View>\n );\n});\n\n/** A bottom sheet over a blurred, dimmed screen, with a Done button under the picker. */\nfunction Sheet({ screen, bottomInset = 0, children }: DemoProps & { children: React.ReactNode }) {\n const { colors, radius, dark } = useKit();\n return (\n <View\n style={[\n s.frame,\n { backgroundColor: colors.muted },\n screen ? s.frameScreen : { borderRadius: radius.xl, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth },\n ]}\n >\n <View pointerEvents=\"none\" style={StyleSheet.absoluteFill} importantForAccessibility=\"no-hide-descendants\" accessibilityElementsHidden>\n {BLUR.map(([x, y], i) => (\n <View key={i} style={[StyleSheet.absoluteFill, { opacity: 1 / 12, transform: [{ translateX: x }, { translateY: y }] }]}>\n <SettingsScreen />\n </View>\n ))}\n {/* A lighter dim than a modal's, so the screen behind still reads as a screen. */}\n <View style={[StyleSheet.absoluteFill, { backgroundColor: colors.overlay, opacity: dark ? 0.45 : 0.5 }]} />\n </View>\n {/* Raised above the screen: an elevated (lighter) surface in dark mode, and a hairline edge in both. */}\n <View\n style={[\n s.sheet,\n {\n backgroundColor: dark ? colors.border : colors.card,\n borderColor: dark ? alpha(colors.foreground, 0.12) : colors.border,\n borderRadius: radius.scale(32),\n marginBottom: 8 + bottomInset,\n },\n ]}\n >\n <View style={[s.grabber, { backgroundColor: alpha(colors.foreground, dark ? 0.3 : 0.15), borderRadius: radius.capsule(5) }]} />\n {children}\n <Pressable\n accessibilityRole=\"button\"\n style={({ pressed }) => [s.button, { backgroundColor: colors.primary, borderRadius: radius.lg, opacity: pressed ? 0.85 : 1 }]}\n >\n <Text maxFontSizeMultiplier={FONT_CAP} style={[s.buttonText, { color: colors.primaryForeground }]}>Done</Text>\n </Pressable>\n </View>\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n frame: { alignSelf: 'stretch', minHeight: 400, justifyContent: 'flex-end', overflow: 'hidden', paddingHorizontal: 8 },\n frameScreen: { flex: 1 },\n screen: { flex: 1, paddingHorizontal: 16, paddingTop: 20, gap: 14 },\n card2: { paddingVertical: 16, gap: 10 },\n group: { paddingHorizontal: 14 },\n row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', minHeight: 50 },\n toggle: { width: 46, height: 28, padding: 2, justifyContent: 'center' },\n knob: { width: 24, height: 24 },\n sheet: { paddingHorizontal: 16, paddingTop: 10, paddingBottom: 16, gap: 10, borderWidth: StyleSheet.hairlineWidth },\n grabber: { alignSelf: 'center', width: 40, height: 5 },\n button: { minHeight: 52, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16 },\n buttonText: { fontSize: 16, fontWeight: '600' },\n});\n\nexport default function Reminder(props: DemoProps) {\n const [time, setTime] = useState<TimeValue>({ hours: 2, minutes: 15 });\n return (\n <Sheet {...props}>\n <RulerTimePicker label=\"Reminder time:\" value={time} onChange={setTime} />\n </Sheet>\n );\n}\n"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "Delivery",
|
|
143
|
+
"title": "Delivery",
|
|
144
|
+
"code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { RulerTimePicker, type TimeValue } from '@/components/ui/ruler-time-picker';\nimport { alpha, useKit } from '@/lib/kit';\n\n/** Controls stop at iOS's largest standard text size; content text stays uncapped. */\nconst FONT_CAP = 1.35;\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\nconst BLUR: [number, number][] = [2, 4, 7, 10].flatMap((r, ring) =>\n Array.from({ length: 8 }, (_, i): [number, number] => {\n const a = ((i + ring / 2) / 8) * Math.PI * 2;\n return [Math.cos(a) * r, Math.sin(a) * r];\n }),\n);\n\n/** The settings screen the sheet was opened from, as blocks: a title, a grouped list and toggles. */\nconst SettingsScreen = React.memo(function SettingsScreen() {\n const { colors, radius, dark } = useKit();\n // In dark mode the grouped rows sit a step lighter than the screen, like iOS Settings.\n const group = dark ? colors.secondary : colors.card;\n const rows: [number, 'value' | 'on' | 'off'][] = [\n [0.42, 'value'],\n [0.3, 'value'],\n [0.38, 'on'],\n [0.34, 'on'],\n [0.4, 'off'],\n [0.28, 'value'],\n ];\n const bar = (w: number | `${number}%`, h: number, color: string) => (\n <View style={{ width: w, height: h, backgroundColor: color, borderRadius: radius.capsule(h) }} />\n );\n return (\n <View style={s.screen}>\n {bar(150, 30, alpha(colors.foreground, 0.7))}\n <View style={[s.group, { backgroundColor: group, borderRadius: radius.lg }]}>\n {rows.map(([w, kind], i) => (\n <View key={i} style={[s.row, i > 0 && { borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: colors.border }]}>\n {bar(`${w * 100}%`, 14, alpha(colors.foreground, 0.45))}\n {kind === 'value' ? (\n bar(64, 14, colors.mutedForeground)\n ) : (\n <View style={[s.toggle, { backgroundColor: kind === 'on' ? colors.accent : colors.border, borderRadius: radius.capsule(28) }]}>\n <View style={[s.knob, { backgroundColor: colors.background, alignSelf: kind === 'on' ? 'flex-end' : 'flex-start', borderRadius: radius.capsule(24) }]} />\n </View>\n )}\n </View>\n ))}\n </View>\n <View style={[s.group, s.card2, { backgroundColor: group, borderRadius: radius.lg }]}>\n {bar('55%', 14, alpha(colors.foreground, 0.45))}\n {bar('80%', 12, colors.mutedForeground)}\n </View>\n </View>\n );\n});\n\n/** A bottom sheet over a blurred, dimmed screen, with a Done button under the picker. */\nfunction Sheet({ screen, bottomInset = 0, children }: DemoProps & { children: React.ReactNode }) {\n const { colors, radius, dark } = useKit();\n return (\n <View\n style={[\n s.frame,\n { backgroundColor: colors.muted },\n screen ? s.frameScreen : { borderRadius: radius.xl, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth },\n ]}\n >\n <View pointerEvents=\"none\" style={StyleSheet.absoluteFill} importantForAccessibility=\"no-hide-descendants\" accessibilityElementsHidden>\n {BLUR.map(([x, y], i) => (\n <View key={i} style={[StyleSheet.absoluteFill, { opacity: 1 / 12, transform: [{ translateX: x }, { translateY: y }] }]}>\n <SettingsScreen />\n </View>\n ))}\n {/* A lighter dim than a modal's, so the screen behind still reads as a screen. */}\n <View style={[StyleSheet.absoluteFill, { backgroundColor: colors.overlay, opacity: dark ? 0.45 : 0.5 }]} />\n </View>\n {/* Raised above the screen: an elevated (lighter) surface in dark mode, and a hairline edge in both. */}\n <View\n style={[\n s.sheet,\n {\n backgroundColor: dark ? colors.border : colors.card,\n borderColor: dark ? alpha(colors.foreground, 0.12) : colors.border,\n borderRadius: radius.scale(32),\n marginBottom: 8 + bottomInset,\n },\n ]}\n >\n <View style={[s.grabber, { backgroundColor: alpha(colors.foreground, dark ? 0.3 : 0.15), borderRadius: radius.capsule(5) }]} />\n {children}\n <Pressable\n accessibilityRole=\"button\"\n style={({ pressed }) => [s.button, { backgroundColor: colors.primary, borderRadius: radius.lg, opacity: pressed ? 0.85 : 1 }]}\n >\n <Text maxFontSizeMultiplier={FONT_CAP} style={[s.buttonText, { color: colors.primaryForeground }]}>Done</Text>\n </Pressable>\n </View>\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n frame: { alignSelf: 'stretch', minHeight: 400, justifyContent: 'flex-end', overflow: 'hidden', paddingHorizontal: 8 },\n frameScreen: { flex: 1 },\n screen: { flex: 1, paddingHorizontal: 16, paddingTop: 20, gap: 14 },\n card2: { paddingVertical: 16, gap: 10 },\n group: { paddingHorizontal: 14 },\n row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', minHeight: 50 },\n toggle: { width: 46, height: 28, padding: 2, justifyContent: 'center' },\n knob: { width: 24, height: 24 },\n sheet: { paddingHorizontal: 16, paddingTop: 10, paddingBottom: 16, gap: 10, borderWidth: StyleSheet.hairlineWidth },\n grabber: { alignSelf: 'center', width: 40, height: 5 },\n button: { minHeight: 52, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16 },\n buttonText: { fontSize: 16, fontWeight: '600' },\n});\n\nexport default function Delivery(props: DemoProps) {\n const [today] = useState(() => new Date());\n const [date, setDate] = useState(() => new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2));\n return (\n <Sheet {...props}>\n <RulerTimePicker mode=\"date\" label=\"Delivery date:\" value={date} onChange={setDate} minDate={today} />\n </Sheet>\n );\n}\n"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
"\"Scratch to reveal\" / —",
|
|
27
27
|
"Printed on the foil."
|
|
28
28
|
],
|
|
29
|
+
[
|
|
30
|
+
"revealHint",
|
|
31
|
+
"string",
|
|
32
|
+
"\"Double-tap to reveal\"",
|
|
33
|
+
"Screen-reader hint on the foil; pass your own to translate it."
|
|
34
|
+
],
|
|
29
35
|
[
|
|
30
36
|
"threshold",
|
|
31
37
|
"number",
|
|
@@ -102,7 +108,7 @@
|
|
|
102
108
|
],
|
|
103
109
|
[
|
|
104
110
|
"Screen readers",
|
|
105
|
-
"The foil is a button labelled with label and sublabel, with the hint 'Double-tap to reveal'."
|
|
111
|
+
"The foil is a button labelled with label and sublabel, with the hint revealHint (default 'Double-tap to reveal')."
|
|
106
112
|
]
|
|
107
113
|
],
|
|
108
114
|
"usage": null,
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
[
|
|
77
77
|
"placeholder",
|
|
78
78
|
"string",
|
|
79
|
-
"
|
|
79
|
+
"labels.selectPlaceholder",
|
|
80
80
|
"Shown in the field while open with nothing selected."
|
|
81
81
|
],
|
|
82
82
|
[
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
[
|
|
107
107
|
"searchPlaceholder",
|
|
108
108
|
"string",
|
|
109
|
-
"
|
|
109
|
+
"labels.search",
|
|
110
110
|
"Placeholder of the filter field."
|
|
111
111
|
],
|
|
112
112
|
[
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
[
|
|
12
12
|
"label",
|
|
13
13
|
"string",
|
|
14
|
-
"
|
|
14
|
+
"labels.slideToConfirm",
|
|
15
15
|
"Shimmering text in the track."
|
|
16
16
|
],
|
|
17
17
|
[
|
|
18
18
|
"confirmedLabel",
|
|
19
19
|
"string",
|
|
20
|
-
"
|
|
20
|
+
"labels.confirmed",
|
|
21
21
|
"Text once completed."
|
|
22
22
|
],
|
|
23
23
|
[
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
[
|
|
102
102
|
"label",
|
|
103
103
|
"string",
|
|
104
|
-
"
|
|
104
|
+
"labels.time",
|
|
105
105
|
"Sheet: field label."
|
|
106
106
|
],
|
|
107
107
|
[
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
[
|
|
120
120
|
"placeholder",
|
|
121
121
|
"string",
|
|
122
|
-
"
|
|
122
|
+
"labels.selectTime",
|
|
123
123
|
"Sheet: shown while nothing is picked."
|
|
124
124
|
],
|
|
125
125
|
[
|
|
@@ -31,6 +31,12 @@
|
|
|
31
31
|
"string",
|
|
32
32
|
"auto summary",
|
|
33
33
|
"What screen readers announce; defaults to a summary of the data."
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"accessibilityHint",
|
|
37
|
+
"string",
|
|
38
|
+
"\"Swipe up or down to read each …\"",
|
|
39
|
+
"Screen-reader hint for the swipe-to-read gesture; pass your own to translate it."
|
|
34
40
|
]
|
|
35
41
|
],
|
|
36
42
|
"behavior": [],
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "toast",
|
|
3
3
|
"category": "Feedback",
|
|
4
4
|
"aliases": [],
|
|
5
|
-
"exportName": "
|
|
5
|
+
"exportName": "Toaster",
|
|
6
6
|
"files": [
|
|
7
7
|
"src/components/ui/toast.tsx"
|
|
8
8
|
],
|
|
@@ -90,7 +90,19 @@
|
|
|
90
90
|
"<Toaster> offset / gap",
|
|
91
91
|
"number",
|
|
92
92
|
"16 (island 10) / 10",
|
|
93
|
-
"Edge distance and fan-out spacing.
|
|
93
|
+
"Edge distance and fan-out spacing. Added on top of safeArea and bottomInset."
|
|
94
|
+
],
|
|
95
|
+
[
|
|
96
|
+
"<Toaster> safeArea",
|
|
97
|
+
"boolean",
|
|
98
|
+
"false",
|
|
99
|
+
"Clear the notch / Dynamic Island and home indicator using react-native-safe-area-context's insets (when installed; every Expo Router app has it)."
|
|
100
|
+
],
|
|
101
|
+
[
|
|
102
|
+
"<Toaster> bottomInset",
|
|
103
|
+
"number",
|
|
104
|
+
"0",
|
|
105
|
+
"Extra space under a bottom stack for a tab bar or composer: <Toaster safeArea bottomInset={49} /> in your (tabs) layout."
|
|
94
106
|
],
|
|
95
107
|
[
|
|
96
108
|
"<Toaster> closeButton",
|
|
@@ -139,7 +151,7 @@
|
|
|
139
151
|
"Each toast is an alert in a polite live region, labelled by its title and description, with action and Dismiss buttons."
|
|
140
152
|
]
|
|
141
153
|
],
|
|
142
|
-
"usage": "import { toast, Toaster } from '@/components/ui/toast';\n\n// once, at the root of your app\n<Toaster />\n\n// anywhere\ntoast.success('Invoice INV-0042 sent', { description: 'Maya will get it by email.' });",
|
|
154
|
+
"usage": "import { toast, Toaster } from '@/components/ui/toast';\n\n// once, at the root of your app (safeArea keeps it clear of the notch and home indicator)\n<Toaster safeArea />\n\n// above a tab bar: in app/(tabs)/_layout.tsx, next to <Tabs />\n<Toaster safeArea bottomInset={49} />\n\n// anywhere\ntoast.success('Invoice INV-0042 sent', { description: 'Maya will get it by email.' });",
|
|
143
155
|
"examples": [
|
|
144
156
|
{
|
|
145
157
|
"name": "Default",
|
|
@@ -31,6 +31,12 @@
|
|
|
31
31
|
"string",
|
|
32
32
|
"auto summary",
|
|
33
33
|
"What screen readers announce; defaults to a summary of the data."
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"accessibilityHint",
|
|
37
|
+
"string",
|
|
38
|
+
"\"Swipe up or down to read each …\"",
|
|
39
|
+
"Screen-reader hint for the swipe-to-read gesture; pass your own to translate it."
|
|
34
40
|
]
|
|
35
41
|
],
|
|
36
42
|
"behavior": [],
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
"string",
|
|
38
38
|
"auto summary",
|
|
39
39
|
"What screen readers announce; defaults to a summary of the data."
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"accessibilityHint",
|
|
43
|
+
"string",
|
|
44
|
+
"\"Swipe up or down to read each …\"",
|
|
45
|
+
"Screen-reader hint for the swipe-to-read gesture; pass your own to translate it."
|
|
40
46
|
]
|
|
41
47
|
],
|
|
42
48
|
"behavior": [],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
AccessibilityInfo,
|
|
4
4
|
Animated,
|
|
@@ -59,7 +59,9 @@ export function Accordion({
|
|
|
59
59
|
const [inner, setInner] = useState(defaultValue);
|
|
60
60
|
const open = value ?? inner;
|
|
61
61
|
const openRef = useRef(open);
|
|
62
|
-
|
|
62
|
+
useLayoutEffect(() => {
|
|
63
|
+
openRef.current = open;
|
|
64
|
+
});
|
|
63
65
|
|
|
64
66
|
const toggle = useCallback(
|
|
65
67
|
(v: string) => {
|
|
@@ -131,8 +133,8 @@ export function AccordionItem({ value, title, subtitle, icon, children, disabled
|
|
|
131
133
|
|
|
132
134
|
const [height, setHeight] = useState(0);
|
|
133
135
|
// `progress` drives height (layout → JS driver); `turn` rotates the chevron on the native driver.
|
|
134
|
-
const progress =
|
|
135
|
-
const turn =
|
|
136
|
+
const [progress] = useState(() => new Animated.Value(open ? 1 : 0));
|
|
137
|
+
const [turn] = useState(() => new Animated.Value(open ? 1 : 0));
|
|
136
138
|
|
|
137
139
|
useEffect(() => {
|
|
138
140
|
// Reduce Motion: open and close at once, chevron flips without turning.
|