react-solidlike 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +251 -0
- package/README.md +251 -0
- package/dist/Await.d.ts +46 -0
- package/dist/Await.d.ts.map +1 -0
- package/dist/Dynamic.d.ts +56 -0
- package/dist/Dynamic.d.ts.map +1 -0
- package/dist/ErrorBoundary.d.ts +63 -0
- package/dist/ErrorBoundary.d.ts.map +1 -0
- package/dist/For.d.ts +36 -0
- package/dist/For.d.ts.map +1 -0
- package/dist/If.d.ts +32 -0
- package/dist/If.d.ts.map +1 -0
- package/dist/QueryBoundary.d.ts +61 -0
- package/dist/QueryBoundary.d.ts.map +1 -0
- package/dist/Repeat.d.ts +32 -0
- package/dist/Repeat.d.ts.map +1 -0
- package/dist/Show.d.ts +34 -0
- package/dist/Show.d.ts.map +1 -0
- package/dist/Switch.d.ts +85 -0
- package/dist/Switch.d.ts.map +1 -0
- package/dist/index.cjs +241 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +209 -0
- package/package.json +59 -0
package/README.en.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# react-solidlike
|
|
2
|
+
|
|
3
|
+
English | [中文](./README.md)
|
|
4
|
+
|
|
5
|
+
Declarative React control flow components inspired by Solid.js. Replaces ternary expressions and `array.map()` in JSX, making your component code cleaner and more readable. Supports React and React Native.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install react-solidlike
|
|
11
|
+
# or
|
|
12
|
+
bun add react-solidlike
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Components
|
|
16
|
+
|
|
17
|
+
### `<Show>` - Conditional Rendering
|
|
18
|
+
|
|
19
|
+
Replace ternary expressions for conditional rendering.
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Show } from "react-solidlike";
|
|
23
|
+
|
|
24
|
+
// Basic usage
|
|
25
|
+
<Show when={isLoggedIn}>
|
|
26
|
+
<UserProfile />
|
|
27
|
+
</Show>
|
|
28
|
+
|
|
29
|
+
// With fallback
|
|
30
|
+
<Show when={isLoggedIn} fallback={<LoginButton />}>
|
|
31
|
+
<UserProfile />
|
|
32
|
+
</Show>
|
|
33
|
+
|
|
34
|
+
// Using render props for type-safe value access
|
|
35
|
+
<Show when={user}>
|
|
36
|
+
{(user) => <UserProfile name={user.name} />}
|
|
37
|
+
</Show>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `<For>` - List Rendering
|
|
41
|
+
|
|
42
|
+
Replace `array.map()` for list rendering.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { For } from "react-solidlike";
|
|
46
|
+
|
|
47
|
+
// Basic usage
|
|
48
|
+
<For each={items}>
|
|
49
|
+
{(item) => <ListItem {...item} />}
|
|
50
|
+
</For>
|
|
51
|
+
|
|
52
|
+
// With keyExtractor
|
|
53
|
+
<For each={users} keyExtractor={(user) => user.id}>
|
|
54
|
+
{(user) => <UserCard user={user} />}
|
|
55
|
+
</For>
|
|
56
|
+
|
|
57
|
+
// With fallback for empty arrays
|
|
58
|
+
<For each={items} fallback={<EmptyState />}>
|
|
59
|
+
{(item, index) => <ListItem item={item} index={index} />}
|
|
60
|
+
</For>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `<Switch>` / `<Match>` / `<Default>` - Multi-branch Rendering
|
|
64
|
+
|
|
65
|
+
Replace multiple `if-else` or `switch` statements.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Switch, Match, Default } from "react-solidlike";
|
|
69
|
+
|
|
70
|
+
<Switch>
|
|
71
|
+
<Match when={status === "loading"}>
|
|
72
|
+
<LoadingSpinner />
|
|
73
|
+
</Match>
|
|
74
|
+
<Match when={status === "error"}>
|
|
75
|
+
<ErrorMessage />
|
|
76
|
+
</Match>
|
|
77
|
+
<Match when={status === "success"}>
|
|
78
|
+
<SuccessContent />
|
|
79
|
+
</Match>
|
|
80
|
+
<Default>
|
|
81
|
+
<IdleState />
|
|
82
|
+
</Default>
|
|
83
|
+
</Switch>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### `<Await>` - Async Rendering
|
|
87
|
+
|
|
88
|
+
Wait for Promise to resolve before rendering.
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { Await } from "react-solidlike";
|
|
92
|
+
|
|
93
|
+
// Basic usage
|
|
94
|
+
<Await promise={fetchUser()} loading={<Spinner />}>
|
|
95
|
+
{(user) => <UserProfile user={user} />}
|
|
96
|
+
</Await>
|
|
97
|
+
|
|
98
|
+
// With error handling
|
|
99
|
+
<Await
|
|
100
|
+
promise={fetchData()}
|
|
101
|
+
loading={<Loading />}
|
|
102
|
+
error={(err) => <ErrorMessage message={err.message} />}
|
|
103
|
+
>
|
|
104
|
+
{(data) => <DataView data={data} />}
|
|
105
|
+
</Await>
|
|
106
|
+
|
|
107
|
+
// Supports non-Promise values (for caching scenarios)
|
|
108
|
+
<Await promise={cache ?? fetchData()} loading={<Spinner />}>
|
|
109
|
+
{(data) => <DataView data={data} />}
|
|
110
|
+
</Await>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `<Repeat>` - Repeat Rendering
|
|
114
|
+
|
|
115
|
+
Replace `Array.from({ length: n }).map()`.
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { Repeat } from "react-solidlike";
|
|
119
|
+
|
|
120
|
+
// Render star ratings
|
|
121
|
+
<Repeat times={5}>
|
|
122
|
+
{(i) => <Star key={i} filled={i < rating} />}
|
|
123
|
+
</Repeat>
|
|
124
|
+
|
|
125
|
+
// Generate skeleton placeholders
|
|
126
|
+
<Repeat times={3}>
|
|
127
|
+
{(i) => <SkeletonCard key={i} />}
|
|
128
|
+
</Repeat>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `<Dynamic>` - Dynamic Component
|
|
132
|
+
|
|
133
|
+
Dynamically select component type based on conditions.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { Dynamic } from "react-solidlike";
|
|
137
|
+
|
|
138
|
+
// Dynamic button or link
|
|
139
|
+
<Dynamic
|
|
140
|
+
component={href ? 'a' : 'button'}
|
|
141
|
+
href={href}
|
|
142
|
+
onClick={onClick}
|
|
143
|
+
>
|
|
144
|
+
{label}
|
|
145
|
+
</Dynamic>
|
|
146
|
+
|
|
147
|
+
// With custom components
|
|
148
|
+
<Dynamic
|
|
149
|
+
component={isAdmin ? AdminPanel : UserPanel}
|
|
150
|
+
user={currentUser}
|
|
151
|
+
/>
|
|
152
|
+
|
|
153
|
+
// React Native usage
|
|
154
|
+
<Dynamic
|
|
155
|
+
component={isPressable ? Pressable : View}
|
|
156
|
+
onPress={handlePress}
|
|
157
|
+
>
|
|
158
|
+
<Text>Content</Text>
|
|
159
|
+
</Dynamic>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### `<ErrorBoundary>` - Error Boundary
|
|
163
|
+
|
|
164
|
+
Catch JavaScript errors in child component tree.
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { ErrorBoundary } from "react-solidlike";
|
|
168
|
+
|
|
169
|
+
// Basic usage
|
|
170
|
+
<ErrorBoundary fallback={<ErrorPage />}>
|
|
171
|
+
<App />
|
|
172
|
+
</ErrorBoundary>
|
|
173
|
+
|
|
174
|
+
// With render props for error info and reset function
|
|
175
|
+
<ErrorBoundary
|
|
176
|
+
fallback={(error, reset) => (
|
|
177
|
+
<div>
|
|
178
|
+
<p>Error: {error.message}</p>
|
|
179
|
+
<button onClick={reset}>Retry</button>
|
|
180
|
+
</div>
|
|
181
|
+
)}
|
|
182
|
+
>
|
|
183
|
+
<App />
|
|
184
|
+
</ErrorBoundary>
|
|
185
|
+
|
|
186
|
+
// Auto-reset when resetKey changes
|
|
187
|
+
<ErrorBoundary fallback={<Error />} resetKey={userId}>
|
|
188
|
+
<UserProfile />
|
|
189
|
+
</ErrorBoundary>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### `<QueryBoundary>` - Query Boundary
|
|
193
|
+
|
|
194
|
+
Handle async query states (loading, error, empty, success). Works with `@tanstack/react-query`, SWR, RTK Query, etc.
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { QueryBoundary } from "react-solidlike";
|
|
198
|
+
import { useQuery } from "@tanstack/react-query";
|
|
199
|
+
|
|
200
|
+
function UserList() {
|
|
201
|
+
const query = useQuery({ queryKey: ["users"], queryFn: fetchUsers });
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<QueryBoundary
|
|
205
|
+
query={query}
|
|
206
|
+
loading={<Spinner />}
|
|
207
|
+
error={<ErrorMessage />}
|
|
208
|
+
empty={<NoData />}
|
|
209
|
+
>
|
|
210
|
+
{(users) => (
|
|
211
|
+
<ul>
|
|
212
|
+
{users.map((user) => (
|
|
213
|
+
<li key={user.id}>{user.name}</li>
|
|
214
|
+
))}
|
|
215
|
+
</ul>
|
|
216
|
+
)}
|
|
217
|
+
</QueryBoundary>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### Props
|
|
223
|
+
|
|
224
|
+
| Prop | Type | Description |
|
|
225
|
+
|------|------|-------------|
|
|
226
|
+
| `query` | `QueryResult<T>` | Query result object |
|
|
227
|
+
| `loading` | `ReactNode` | Loading state content |
|
|
228
|
+
| `error` | `ReactNode` | Error state content |
|
|
229
|
+
| `empty` | `ReactNode` | Empty state content |
|
|
230
|
+
| `children` | `ReactNode \| (data: T) => ReactNode` | Success content |
|
|
231
|
+
| `isEmptyFn` | `(data: T) => boolean` | Custom empty check |
|
|
232
|
+
|
|
233
|
+
## Development
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Install dependencies
|
|
237
|
+
bun install
|
|
238
|
+
|
|
239
|
+
# Run tests
|
|
240
|
+
bun test
|
|
241
|
+
|
|
242
|
+
# Lint
|
|
243
|
+
bun run lint
|
|
244
|
+
|
|
245
|
+
# Build
|
|
246
|
+
bun run build
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# react-solidlike
|
|
2
|
+
|
|
3
|
+
[English](./README.en.md) | 中文
|
|
4
|
+
|
|
5
|
+
声明式 React 控制流组件库,灵感来源于 Solid.js。用于替代 JSX 中的三元表达式和 `array.map()`,让你的组件代码更加清晰易读。支持 React 和 React Native。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install react-solidlike
|
|
11
|
+
# 或
|
|
12
|
+
bun add react-solidlike
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 组件
|
|
16
|
+
|
|
17
|
+
### `<Show>` - 条件渲染
|
|
18
|
+
|
|
19
|
+
替代三元表达式进行条件渲染。
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Show } from "react-solidlike";
|
|
23
|
+
|
|
24
|
+
// 基础用法
|
|
25
|
+
<Show when={isLoggedIn}>
|
|
26
|
+
<UserProfile />
|
|
27
|
+
</Show>
|
|
28
|
+
|
|
29
|
+
// 带 fallback
|
|
30
|
+
<Show when={isLoggedIn} fallback={<LoginButton />}>
|
|
31
|
+
<UserProfile />
|
|
32
|
+
</Show>
|
|
33
|
+
|
|
34
|
+
// 使用 render props 获取类型安全的值
|
|
35
|
+
<Show when={user}>
|
|
36
|
+
{(user) => <UserProfile name={user.name} />}
|
|
37
|
+
</Show>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `<For>` - 列表渲染
|
|
41
|
+
|
|
42
|
+
替代 `array.map()` 进行列表渲染。
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { For } from "react-solidlike";
|
|
46
|
+
|
|
47
|
+
// 基础用法
|
|
48
|
+
<For each={items}>
|
|
49
|
+
{(item) => <ListItem {...item} />}
|
|
50
|
+
</For>
|
|
51
|
+
|
|
52
|
+
// 带 keyExtractor
|
|
53
|
+
<For each={users} keyExtractor={(user) => user.id}>
|
|
54
|
+
{(user) => <UserCard user={user} />}
|
|
55
|
+
</For>
|
|
56
|
+
|
|
57
|
+
// 带 fallback 处理空数组
|
|
58
|
+
<For each={items} fallback={<EmptyState />}>
|
|
59
|
+
{(item, index) => <ListItem item={item} index={index} />}
|
|
60
|
+
</For>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `<Switch>` / `<Match>` / `<Default>` - 多分支渲染
|
|
64
|
+
|
|
65
|
+
替代多个 `if-else` 或 `switch` 语句。
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Switch, Match, Default } from "react-solidlike";
|
|
69
|
+
|
|
70
|
+
<Switch>
|
|
71
|
+
<Match when={status === "loading"}>
|
|
72
|
+
<LoadingSpinner />
|
|
73
|
+
</Match>
|
|
74
|
+
<Match when={status === "error"}>
|
|
75
|
+
<ErrorMessage />
|
|
76
|
+
</Match>
|
|
77
|
+
<Match when={status === "success"}>
|
|
78
|
+
<SuccessContent />
|
|
79
|
+
</Match>
|
|
80
|
+
<Default>
|
|
81
|
+
<IdleState />
|
|
82
|
+
</Default>
|
|
83
|
+
</Switch>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### `<Await>` - 异步等待
|
|
87
|
+
|
|
88
|
+
等待 Promise resolve 后渲染内容。
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { Await } from "react-solidlike";
|
|
92
|
+
|
|
93
|
+
// 基础用法
|
|
94
|
+
<Await promise={fetchUser()} loading={<Spinner />}>
|
|
95
|
+
{(user) => <UserProfile user={user} />}
|
|
96
|
+
</Await>
|
|
97
|
+
|
|
98
|
+
// 带错误处理
|
|
99
|
+
<Await
|
|
100
|
+
promise={fetchData()}
|
|
101
|
+
loading={<Loading />}
|
|
102
|
+
error={(err) => <ErrorMessage message={err.message} />}
|
|
103
|
+
>
|
|
104
|
+
{(data) => <DataView data={data} />}
|
|
105
|
+
</Await>
|
|
106
|
+
|
|
107
|
+
// 支持非 Promise 值(用于缓存场景)
|
|
108
|
+
<Await promise={cache ?? fetchData()} loading={<Spinner />}>
|
|
109
|
+
{(data) => <DataView data={data} />}
|
|
110
|
+
</Await>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `<Repeat>` - 重复渲染
|
|
114
|
+
|
|
115
|
+
替代 `Array.from({ length: n }).map()`。
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { Repeat } from "react-solidlike";
|
|
119
|
+
|
|
120
|
+
// 渲染星级评分
|
|
121
|
+
<Repeat times={5}>
|
|
122
|
+
{(i) => <Star key={i} filled={i < rating} />}
|
|
123
|
+
</Repeat>
|
|
124
|
+
|
|
125
|
+
// 生成骨架屏占位
|
|
126
|
+
<Repeat times={3}>
|
|
127
|
+
{(i) => <SkeletonCard key={i} />}
|
|
128
|
+
</Repeat>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `<Dynamic>` - 动态组件
|
|
132
|
+
|
|
133
|
+
根据条件动态选择要渲染的组件类型。
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { Dynamic } from "react-solidlike";
|
|
137
|
+
|
|
138
|
+
// 动态选择按钮或链接
|
|
139
|
+
<Dynamic
|
|
140
|
+
component={href ? 'a' : 'button'}
|
|
141
|
+
href={href}
|
|
142
|
+
onClick={onClick}
|
|
143
|
+
>
|
|
144
|
+
{label}
|
|
145
|
+
</Dynamic>
|
|
146
|
+
|
|
147
|
+
// 配合自定义组件
|
|
148
|
+
<Dynamic
|
|
149
|
+
component={isAdmin ? AdminPanel : UserPanel}
|
|
150
|
+
user={currentUser}
|
|
151
|
+
/>
|
|
152
|
+
|
|
153
|
+
// React Native 中使用
|
|
154
|
+
<Dynamic
|
|
155
|
+
component={isPressable ? Pressable : View}
|
|
156
|
+
onPress={handlePress}
|
|
157
|
+
>
|
|
158
|
+
<Text>Content</Text>
|
|
159
|
+
</Dynamic>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### `<ErrorBoundary>` - 错误边界
|
|
163
|
+
|
|
164
|
+
捕获子组件树中的 JavaScript 错误,防止整个应用崩溃。
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { ErrorBoundary } from "react-solidlike";
|
|
168
|
+
|
|
169
|
+
// 基础用法
|
|
170
|
+
<ErrorBoundary fallback={<ErrorPage />}>
|
|
171
|
+
<App />
|
|
172
|
+
</ErrorBoundary>
|
|
173
|
+
|
|
174
|
+
// 使用 render props 获取错误信息和重置函数
|
|
175
|
+
<ErrorBoundary
|
|
176
|
+
fallback={(error, reset) => (
|
|
177
|
+
<div>
|
|
178
|
+
<p>Error: {error.message}</p>
|
|
179
|
+
<button onClick={reset}>Retry</button>
|
|
180
|
+
</div>
|
|
181
|
+
)}
|
|
182
|
+
>
|
|
183
|
+
<App />
|
|
184
|
+
</ErrorBoundary>
|
|
185
|
+
|
|
186
|
+
// resetKey 变化时自动重置
|
|
187
|
+
<ErrorBoundary fallback={<Error />} resetKey={userId}>
|
|
188
|
+
<UserProfile />
|
|
189
|
+
</ErrorBoundary>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### `<QueryBoundary>` - 查询边界
|
|
193
|
+
|
|
194
|
+
处理异步查询的各种状态(加载中、错误、空数据、成功)。可与 `@tanstack/react-query`、SWR、RTK Query 等配合使用。
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
import { QueryBoundary } from "react-solidlike";
|
|
198
|
+
import { useQuery } from "@tanstack/react-query";
|
|
199
|
+
|
|
200
|
+
function UserList() {
|
|
201
|
+
const query = useQuery({ queryKey: ["users"], queryFn: fetchUsers });
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<QueryBoundary
|
|
205
|
+
query={query}
|
|
206
|
+
loading={<Spinner />}
|
|
207
|
+
error={<ErrorMessage />}
|
|
208
|
+
empty={<NoData />}
|
|
209
|
+
>
|
|
210
|
+
{(users) => (
|
|
211
|
+
<ul>
|
|
212
|
+
{users.map((user) => (
|
|
213
|
+
<li key={user.id}>{user.name}</li>
|
|
214
|
+
))}
|
|
215
|
+
</ul>
|
|
216
|
+
)}
|
|
217
|
+
</QueryBoundary>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### Props
|
|
223
|
+
|
|
224
|
+
| 属性 | 类型 | 描述 |
|
|
225
|
+
|------|------|------|
|
|
226
|
+
| `query` | `QueryResult<T>` | 查询结果对象 |
|
|
227
|
+
| `loading` | `ReactNode` | 加载中显示 |
|
|
228
|
+
| `error` | `ReactNode` | 错误时显示 |
|
|
229
|
+
| `empty` | `ReactNode` | 空数据显示 |
|
|
230
|
+
| `children` | `ReactNode \| (data: T) => ReactNode` | 成功时渲染 |
|
|
231
|
+
| `isEmptyFn` | `(data: T) => boolean` | 自定义空判断 |
|
|
232
|
+
|
|
233
|
+
## 开发
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# 安装依赖
|
|
237
|
+
bun install
|
|
238
|
+
|
|
239
|
+
# 运行测试
|
|
240
|
+
bun test
|
|
241
|
+
|
|
242
|
+
# 代码检查
|
|
243
|
+
bun run lint
|
|
244
|
+
|
|
245
|
+
# 构建
|
|
246
|
+
bun run build
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT
|
package/dist/Await.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface AwaitProps<T> {
|
|
3
|
+
/** Promise to wait for | 要等待的 Promise */
|
|
4
|
+
promise: Promise<T> | T;
|
|
5
|
+
/** Content to show when Promise is pending | Promise pending 时显示的内容 */
|
|
6
|
+
loading?: ReactNode;
|
|
7
|
+
/** Content to show when Promise is rejected | Promise rejected 时显示的内容 */
|
|
8
|
+
error?: ReactNode | ((error: unknown) => ReactNode);
|
|
9
|
+
/** Content to render when Promise is fulfilled | Promise fulfilled 时渲染的内容 */
|
|
10
|
+
children: ReactNode | ((data: T) => ReactNode);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Async await component, handles various Promise states
|
|
14
|
+
*
|
|
15
|
+
* 异步等待组件,用于处理 Promise 的各种状态
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Basic usage | 基础用法
|
|
19
|
+
* <Await promise={fetchUser()} loading={<Spinner />}>
|
|
20
|
+
* {(user) => <UserProfile user={user} />}
|
|
21
|
+
* </Await>
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // With error handling | 带错误处理
|
|
25
|
+
* <Await
|
|
26
|
+
* promise={fetchData()}
|
|
27
|
+
* loading={<Loading />}
|
|
28
|
+
* error={(err) => <ErrorMessage message={err.message} />}
|
|
29
|
+
* >
|
|
30
|
+
* {(data) => <DataView data={data} />}
|
|
31
|
+
* </Await>
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Static children (doesn't need Promise value) | 静态 children(不需要 Promise 的值)
|
|
35
|
+
* <Await promise={initApp()} loading={<SplashScreen />}>
|
|
36
|
+
* <App />
|
|
37
|
+
* </Await>
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Renders immediately for non-Promise values (sync values) | 传入非 Promise 值时直接渲染(同步值)
|
|
41
|
+
* <Await promise={cachedData ?? fetchData()} loading={<Spinner />}>
|
|
42
|
+
* {(data) => <DataView data={data} />}
|
|
43
|
+
* </Await>
|
|
44
|
+
*/
|
|
45
|
+
export declare function Await<T>({ promise, loading, error, children }: AwaitProps<T>): ReactNode;
|
|
46
|
+
//# sourceMappingURL=Await.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Await.d.ts","sourceRoot":"","sources":["../src/Await.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAQ5D,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,uEAAuE;IACvE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC;IACpD,6EAA6E;IAC7E,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,OAAc,EAAE,KAAY,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAyDtG"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type ComponentProps, type ElementType, type ReactNode } from "react";
|
|
2
|
+
/** Get component props type | 获取组件的 props 类型 */
|
|
3
|
+
type PropsOf<T extends ElementType> = ComponentProps<T>;
|
|
4
|
+
export type DynamicProps<T extends ElementType> = {
|
|
5
|
+
/** Component or element type to render | 要渲染的组件或元素类型 */
|
|
6
|
+
component: T | null | undefined | false;
|
|
7
|
+
/** Fallback content when component is falsy | 当 component 为 falsy 时渲染的备选内容 */
|
|
8
|
+
fallback?: ReactNode;
|
|
9
|
+
} & PropsOf<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Dynamic component rendering, selects component type based on conditions
|
|
12
|
+
*
|
|
13
|
+
* 动态组件渲染,根据条件选择要渲染的组件类型
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Basic usage - select component based on condition | 基础用法 - 根据条件选择组件
|
|
17
|
+
* <Dynamic component={isExternal ? 'a' : Link} href={url}>
|
|
18
|
+
* Click me
|
|
19
|
+
* </Dynamic>
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Dynamic button or link | 动态选择按钮或链接
|
|
23
|
+
* <Dynamic
|
|
24
|
+
* component={href ? 'a' : 'button'}
|
|
25
|
+
* href={href}
|
|
26
|
+
* onClick={onClick}
|
|
27
|
+
* >
|
|
28
|
+
* {label}
|
|
29
|
+
* </Dynamic>
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // With custom components | 配合自定义组件
|
|
33
|
+
* <Dynamic
|
|
34
|
+
* component={isAdmin ? AdminPanel : UserPanel}
|
|
35
|
+
* user={currentUser}
|
|
36
|
+
* />
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Using fallback | 使用 fallback
|
|
40
|
+
* <Dynamic component={customComponent} fallback={<DefaultComponent />}>
|
|
41
|
+
* Content
|
|
42
|
+
* </Dynamic>
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // React Native usage | React Native 中使用
|
|
46
|
+
* <Dynamic
|
|
47
|
+
* component={isPressable ? Pressable : View}
|
|
48
|
+
* onPress={handlePress}
|
|
49
|
+
* style={styles.container}
|
|
50
|
+
* >
|
|
51
|
+
* <Text>Content</Text>
|
|
52
|
+
* </Dynamic>
|
|
53
|
+
*/
|
|
54
|
+
export declare function Dynamic<T extends ElementType>({ component, fallback, ...props }: DynamicProps<T>): ReactNode;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=Dynamic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dynamic.d.ts","sourceRoot":"","sources":["../src/Dynamic.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAqC,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjH,gDAAgD;AAChD,KAAK,OAAO,CAAC,CAAC,SAAS,WAAW,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;AAExD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,WAAW,IAAI;IAC9C,wDAAwD;IACxD,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC;IACxC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,WAAW,EAAE,EAAE,SAAS,EAAE,QAAe,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAMnH"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Component, type ErrorInfo, type ReactNode } from "react";
|
|
2
|
+
export interface ErrorBoundaryProps {
|
|
3
|
+
/** Content to show when error occurs | 发生错误时显示的内容 */
|
|
4
|
+
fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
5
|
+
/** Child components | 子组件 */
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/** Callback when error occurs | 错误发生时的回调 */
|
|
8
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
9
|
+
/** Key to reset error boundary, auto-resets when key changes | 用于重置错误边界的 key,当 key 变化时自动重置 */
|
|
10
|
+
resetKey?: unknown;
|
|
11
|
+
}
|
|
12
|
+
interface ErrorBoundaryState {
|
|
13
|
+
error: Error | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Error boundary component, catches JavaScript errors in child component tree
|
|
17
|
+
*
|
|
18
|
+
* 错误边界组件,捕获子组件树中的 JavaScript 错误
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Basic usage | 基础用法
|
|
22
|
+
* <ErrorBoundary fallback={<ErrorPage />}>
|
|
23
|
+
* <App />
|
|
24
|
+
* </ErrorBoundary>
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Using render props for error info and reset function | 使用 render props 获取错误信息和重置函数
|
|
28
|
+
* <ErrorBoundary
|
|
29
|
+
* fallback={(error, reset) => (
|
|
30
|
+
* <div>
|
|
31
|
+
* <p>Error: {error.message}</p>
|
|
32
|
+
* <button onClick={reset}>Retry</button>
|
|
33
|
+
* </div>
|
|
34
|
+
* )}
|
|
35
|
+
* >
|
|
36
|
+
* <App />
|
|
37
|
+
* </ErrorBoundary>
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Using resetKey for auto-reset (when key changes) | 使用 resetKey 自动重置(当 key 变化时)
|
|
41
|
+
* <ErrorBoundary fallback={<Error />} resetKey={userId}>
|
|
42
|
+
* <UserProfile />
|
|
43
|
+
* </ErrorBoundary>
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // With onError for error reporting | 配合 onError 进行错误上报
|
|
47
|
+
* <ErrorBoundary
|
|
48
|
+
* fallback={<Error />}
|
|
49
|
+
* onError={(error, info) => reportError(error, info)}
|
|
50
|
+
* >
|
|
51
|
+
* <App />
|
|
52
|
+
* </ErrorBoundary>
|
|
53
|
+
*/
|
|
54
|
+
export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
55
|
+
constructor(props: ErrorBoundaryProps);
|
|
56
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
57
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
58
|
+
componentDidUpdate(prevProps: ErrorBoundaryProps): void;
|
|
59
|
+
reset: () => void;
|
|
60
|
+
render(): ReactNode;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=ErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../src/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE,MAAM,WAAW,kBAAkB;IAC/B,qDAAqD;IACrD,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC,CAAC;IACvE,6BAA6B;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;IACvD,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,kBAAkB;IACxB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBAAa,aAAc,SAAQ,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;gBACpE,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,kBAAkB;IAIjE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IAI3D,kBAAkB,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI;IAOvD,KAAK,QAAO,IAAI,CAEd;IAEF,MAAM,IAAI,SAAS;CAatB"}
|