react-solidlike 2.2.3 → 2.3.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 +70 -0
- package/README.md +70 -0
- package/dist/For.d.ts +5 -3
- package/dist/Repeat.d.ts +4 -7
- package/dist/Split.d.ts +49 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +35 -10
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -63,6 +63,22 @@ import { For } from "react-solidlike";
|
|
|
63
63
|
<For each={items} wrapper={<ul className="list" />}>
|
|
64
64
|
{(item) => <li>{item.name}</li>}
|
|
65
65
|
</For>
|
|
66
|
+
|
|
67
|
+
// Reverse rendering
|
|
68
|
+
<For each={messages} reverse>
|
|
69
|
+
{(msg) => <Message {...msg} />}
|
|
70
|
+
</For>
|
|
71
|
+
|
|
72
|
+
// Using array parameter for context
|
|
73
|
+
<For each={steps}>
|
|
74
|
+
{(step, index, array) => (
|
|
75
|
+
<Step
|
|
76
|
+
data={step}
|
|
77
|
+
isFirst={index === 0}
|
|
78
|
+
isLast={index === array.length - 1}
|
|
79
|
+
/>
|
|
80
|
+
)}
|
|
81
|
+
</For>
|
|
66
82
|
```
|
|
67
83
|
|
|
68
84
|
### `<Switch>` / `<Match>` / `<Default>` - Multi-branch Rendering
|
|
@@ -136,6 +152,60 @@ import { Repeat } from "react-solidlike";
|
|
|
136
152
|
<Repeat times={5} wrapper={<div className="stars" />}>
|
|
137
153
|
{(i) => <Star key={i} />}
|
|
138
154
|
</Repeat>
|
|
155
|
+
|
|
156
|
+
// Reverse rendering
|
|
157
|
+
<Repeat times={5} reverse>
|
|
158
|
+
{(i) => <div key={i}>Reversed {i}</div>}
|
|
159
|
+
</Repeat>
|
|
160
|
+
|
|
161
|
+
// Using length parameter for progress
|
|
162
|
+
<Repeat times={totalSteps}>
|
|
163
|
+
{(i, length) => (
|
|
164
|
+
<Step key={i} current={i + 1} total={length} />
|
|
165
|
+
)}
|
|
166
|
+
</Repeat>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `<Split>` - String Split Rendering
|
|
170
|
+
|
|
171
|
+
Split a string by separator and render each part.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { Split } from "react-solidlike";
|
|
175
|
+
|
|
176
|
+
// Basic usage - splits without keeping separator
|
|
177
|
+
<Split string="a,b,c" separator=",">
|
|
178
|
+
{(part) => <span>{part}</span>}
|
|
179
|
+
</Split>
|
|
180
|
+
// Renders: ["a", "b", "c"]
|
|
181
|
+
|
|
182
|
+
// Keep separator in result
|
|
183
|
+
<Split string="9+5=(9+1)+4" separator="=" keepSeparator>
|
|
184
|
+
{(part) => <span>{part}</span>}
|
|
185
|
+
</Split>
|
|
186
|
+
// Renders: ["9+5", "=", "(9+1)+4"]
|
|
187
|
+
|
|
188
|
+
// Using RegExp separator
|
|
189
|
+
<Split string="a1b2c3" separator={/\d/} keepSeparator>
|
|
190
|
+
{(part) => <span>{part}</span>}
|
|
191
|
+
</Split>
|
|
192
|
+
// Renders: ["a", "1", "b", "2", "c", "3"]
|
|
193
|
+
|
|
194
|
+
// With wrapper element
|
|
195
|
+
<Split string="hello world" separator=" " wrapper={<div className="words" />}>
|
|
196
|
+
{(word) => <span>{word}</span>}
|
|
197
|
+
</Split>
|
|
198
|
+
|
|
199
|
+
// With fallback for empty string
|
|
200
|
+
<Split string={text} separator="," fallback={<EmptyState />}>
|
|
201
|
+
{(part) => <Tag>{part}</Tag>}
|
|
202
|
+
</Split>
|
|
203
|
+
|
|
204
|
+
// Reverse rendering
|
|
205
|
+
<Split string="a,b,c" separator="," reverse>
|
|
206
|
+
{(part) => <span>{part}</span>}
|
|
207
|
+
</Split>
|
|
208
|
+
// Render order: ["c", "b", "a"]
|
|
139
209
|
```
|
|
140
210
|
|
|
141
211
|
### `<Dynamic>` - Dynamic Component
|
package/README.md
CHANGED
|
@@ -63,6 +63,22 @@ import { For } from "react-solidlike";
|
|
|
63
63
|
<For each={items} wrapper={<ul className="list" />}>
|
|
64
64
|
{(item) => <li>{item.name}</li>}
|
|
65
65
|
</For>
|
|
66
|
+
|
|
67
|
+
// 倒序渲染
|
|
68
|
+
<For each={messages} reverse>
|
|
69
|
+
{(msg) => <Message {...msg} />}
|
|
70
|
+
</For>
|
|
71
|
+
|
|
72
|
+
// 使用 array 参数获取上下文信息
|
|
73
|
+
<For each={steps}>
|
|
74
|
+
{(step, index, array) => (
|
|
75
|
+
<Step
|
|
76
|
+
data={step}
|
|
77
|
+
isFirst={index === 0}
|
|
78
|
+
isLast={index === array.length - 1}
|
|
79
|
+
/>
|
|
80
|
+
)}
|
|
81
|
+
</For>
|
|
66
82
|
```
|
|
67
83
|
|
|
68
84
|
### `<Switch>` / `<Match>` / `<Default>` - 多分支渲染
|
|
@@ -136,6 +152,60 @@ import { Repeat } from "react-solidlike";
|
|
|
136
152
|
<Repeat times={5} wrapper={<div className="stars" />}>
|
|
137
153
|
{(i) => <Star key={i} />}
|
|
138
154
|
</Repeat>
|
|
155
|
+
|
|
156
|
+
// 倒序渲染
|
|
157
|
+
<Repeat times={5} reverse>
|
|
158
|
+
{(i) => <div key={i}>倒序 {i}</div>}
|
|
159
|
+
</Repeat>
|
|
160
|
+
|
|
161
|
+
// 使用 length 参数显示进度
|
|
162
|
+
<Repeat times={totalSteps}>
|
|
163
|
+
{(i, length) => (
|
|
164
|
+
<Step key={i} current={i + 1} total={length} />
|
|
165
|
+
)}
|
|
166
|
+
</Repeat>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `<Split>` - 字符串切割渲染
|
|
170
|
+
|
|
171
|
+
按分隔符切割字符串并渲染每个部分。
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { Split } from "react-solidlike";
|
|
175
|
+
|
|
176
|
+
// 基础用法 - 切割后不保留分隔符
|
|
177
|
+
<Split string="a,b,c" separator=",">
|
|
178
|
+
{(part) => <span>{part}</span>}
|
|
179
|
+
</Split>
|
|
180
|
+
// 渲染: ["a", "b", "c"]
|
|
181
|
+
|
|
182
|
+
// 保留分隔符
|
|
183
|
+
<Split string="9+5=(9+1)+4" separator="=" keepSeparator>
|
|
184
|
+
{(part) => <span>{part}</span>}
|
|
185
|
+
</Split>
|
|
186
|
+
// 渲染: ["9+5", "=", "(9+1)+4"]
|
|
187
|
+
|
|
188
|
+
// 使用正则表达式分隔符
|
|
189
|
+
<Split string="a1b2c3" separator={/\d/} keepSeparator>
|
|
190
|
+
{(part) => <span>{part}</span>}
|
|
191
|
+
</Split>
|
|
192
|
+
// 渲染: ["a", "1", "b", "2", "c", "3"]
|
|
193
|
+
|
|
194
|
+
// 带 wrapper 包装元素
|
|
195
|
+
<Split string="hello world" separator=" " wrapper={<div className="words" />}>
|
|
196
|
+
{(word) => <span>{word}</span>}
|
|
197
|
+
</Split>
|
|
198
|
+
|
|
199
|
+
// 带 fallback 处理空字符串
|
|
200
|
+
<Split string={text} separator="," fallback={<EmptyState />}>
|
|
201
|
+
{(part) => <Tag>{part}</Tag>}
|
|
202
|
+
</Split>
|
|
203
|
+
|
|
204
|
+
// 倒序渲染
|
|
205
|
+
<Split string="a,b,c" separator="," reverse>
|
|
206
|
+
{(part) => <span>{part}</span>}
|
|
207
|
+
</Split>
|
|
208
|
+
// 渲染顺序: ["c", "b", "a"]
|
|
139
209
|
```
|
|
140
210
|
|
|
141
211
|
### `<Dynamic>` - 动态组件
|
package/dist/For.d.ts
CHANGED
|
@@ -2,14 +2,16 @@ import { type Key, type ReactElement, type ReactNode } from "react";
|
|
|
2
2
|
export interface ForProps<T> {
|
|
3
3
|
/** Array to iterate over | 要遍历的数组 */
|
|
4
4
|
each: T[] | readonly T[] | null | undefined;
|
|
5
|
-
/** Render function for each element |
|
|
6
|
-
children: (item: T, index: number) => ReactNode;
|
|
5
|
+
/** Render function for each element, receives item, index and original array | 渲染每个元素的函数,接收元素、索引和原数组 */
|
|
6
|
+
children: (item: T, index: number, array: T[] | readonly T[]) => ReactNode;
|
|
7
7
|
/** Function to extract key from element, defaults to index | 从元素中提取 key 的函数,默认使用索引 */
|
|
8
8
|
keyExtractor?: (item: T, index: number) => Key;
|
|
9
9
|
/** Fallback content when array is empty | 数组为空时渲染的备选内容 */
|
|
10
10
|
fallback?: ReactNode;
|
|
11
11
|
/** Wrapper element for all rendered elements | 包装所有渲染元素的元素 */
|
|
12
12
|
wrapper?: ReactElement;
|
|
13
|
+
/** Reverse the rendering order | 倒序渲染 */
|
|
14
|
+
reverse?: boolean;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* List rendering component, replaces array.map() in JSX
|
|
@@ -40,4 +42,4 @@ export interface ForProps<T> {
|
|
|
40
42
|
* {(item) => <li>{item.name}</li>}
|
|
41
43
|
* </For>
|
|
42
44
|
*/
|
|
43
|
-
export declare function For<T>({ each, children, keyExtractor, fallback, wrapper }: ForProps<T>): ReactNode;
|
|
45
|
+
export declare function For<T>({ each, children, keyExtractor, fallback, wrapper, reverse }: ForProps<T>): ReactNode;
|
package/dist/Repeat.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type ForProps } from './For';
|
|
3
|
+
export interface RepeatProps extends Omit<ForProps<number>, 'each'> {
|
|
3
4
|
/** Number of times to repeat | 重复次数 */
|
|
4
5
|
times: number;
|
|
5
|
-
/** Render function, receives current index (starting from 0) | 渲染函数,接收当前索引(从 0 开始) */
|
|
6
|
-
children: (index: number) => ReactNode;
|
|
7
|
-
/** Wrapper element for all rendered elements | 包装所有渲染元素的元素 */
|
|
8
|
-
wrapper?: ReactElement;
|
|
9
6
|
}
|
|
10
7
|
/**
|
|
11
8
|
* Repeat rendering component, replaces Array.from({ length: n }).map()
|
|
@@ -36,4 +33,4 @@ export interface RepeatProps {
|
|
|
36
33
|
* {(i) => <Star key={i} />}
|
|
37
34
|
* </Repeat>
|
|
38
35
|
*/
|
|
39
|
-
export declare function Repeat({ times, children,
|
|
36
|
+
export declare function Repeat({ times, children, ...props }: RepeatProps): ReactNode;
|
package/dist/Split.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type ForProps } from './For';
|
|
3
|
+
export interface SplitProps extends Omit<ForProps<string>, 'each'> {
|
|
4
|
+
/** String to split | 要切割的字符串 */
|
|
5
|
+
string: string | null | undefined;
|
|
6
|
+
/** Separator to split by, can be string or RegExp | 分隔符,可以是字符串或正则表达式 */
|
|
7
|
+
separator: string | RegExp;
|
|
8
|
+
/** Whether to keep separator in result array | 是否在结果数组中保留分隔符 */
|
|
9
|
+
keepSeparator?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* String splitting and rendering component, splits a string by separator and renders each part
|
|
13
|
+
*
|
|
14
|
+
* 字符串切割渲染组件,按分隔符切割字符串并渲染每个部分
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Basic usage | 基础用法
|
|
18
|
+
* <Split string="a,b,c" separator=",">
|
|
19
|
+
* {(part) => <span>{part}</span>}
|
|
20
|
+
* </Split>
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Keep separator | 保留分隔符
|
|
24
|
+
* <Split string="9+5=(9+1)+4" separator="=" keepSeparator>
|
|
25
|
+
* {(part) => <span>{part}</span>}
|
|
26
|
+
* </Split>
|
|
27
|
+
* // Renders: ["9+5", "=", "(9+1)+4"]
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // Without keeping separator | 不保留分隔符
|
|
31
|
+
* <Split string="9+5=(9+1)+4" separator="=">
|
|
32
|
+
* {(part) => <span>{part}</span>}
|
|
33
|
+
* </Split>
|
|
34
|
+
* // Renders: ["9+5", "(9+1)+4"]
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // With RegExp separator | 使用正则表达式分隔符
|
|
38
|
+
* <Split string="a1b2c3" separator={/\d/} keepSeparator>
|
|
39
|
+
* {(part) => <span>{part}</span>}
|
|
40
|
+
* </Split>
|
|
41
|
+
* // Renders: ["a", "1", "b", "2", "c", "3"]
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // With wrapper element | 使用包装元素
|
|
45
|
+
* <Split string="hello world" separator=" " wrapper={<div className="words" />}>
|
|
46
|
+
* {(word) => <span>{word}</span>}
|
|
47
|
+
* </Split>
|
|
48
|
+
*/
|
|
49
|
+
export declare function Split({ string, separator, keepSeparator, children, ...props }: SplitProps): ReactNode;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export { For, type ForProps } from "./For";
|
|
|
5
5
|
export { QueryBoundary, type QueryBoundaryProps, type QueryResult } from "./QueryBoundary";
|
|
6
6
|
export { Repeat, type RepeatProps } from "./Repeat";
|
|
7
7
|
export { Show, type ShowProps } from "./Show";
|
|
8
|
+
export { Split, type SplitProps } from "./Split";
|
|
8
9
|
export { Default, type DefaultProps, Match, type MatchProps, Switch, type SwitchProps } from "./Switch";
|
package/dist/index.js
CHANGED
|
@@ -76,11 +76,12 @@ var ErrorBoundary = class extends Component {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
function For({ each, children, keyExtractor, fallback = null, wrapper }) {
|
|
79
|
+
function For({ each, children, keyExtractor, fallback = null, wrapper, reverse }) {
|
|
80
80
|
if (!each || each.length === 0) return fallback;
|
|
81
|
-
const elements = each.map((item,
|
|
82
|
-
const
|
|
83
|
-
|
|
81
|
+
const elements = (reverse ? [...each].reverse() : each).map((item, i) => {
|
|
82
|
+
const originalIndex = reverse ? each.length - 1 - i : i;
|
|
83
|
+
const key = keyExtractor ? keyExtractor(item, originalIndex) : originalIndex;
|
|
84
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children(item, originalIndex, each) }, key);
|
|
84
85
|
});
|
|
85
86
|
return wrapper && isValidElement(wrapper) ? cloneElement(wrapper, {}, elements) : elements;
|
|
86
87
|
}
|
|
@@ -102,11 +103,13 @@ function QueryBoundary({ query, loading = null, error = null, empty = null, chil
|
|
|
102
103
|
return children;
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
function Repeat({ times, children,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
function Repeat({ times, children, ...props }) {
|
|
107
|
+
const indices = times > 0 ? Array.from({ length: times }, (_, i) => i) : [];
|
|
108
|
+
return /* @__PURE__ */ jsx(For, {
|
|
109
|
+
...props,
|
|
110
|
+
each: indices,
|
|
111
|
+
children: (i, _i, array) => children(i, array.length, array)
|
|
112
|
+
});
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
function Show({ when, children, fallback = null }) {
|
|
@@ -121,6 +124,28 @@ function isEmpty(value) {
|
|
|
121
124
|
return false;
|
|
122
125
|
}
|
|
123
126
|
|
|
127
|
+
function Split({ string, separator, keepSeparator = false, children, ...props }) {
|
|
128
|
+
const parts = splitString(string, separator, keepSeparator);
|
|
129
|
+
return /* @__PURE__ */ jsx(For, {
|
|
130
|
+
...props,
|
|
131
|
+
each: parts,
|
|
132
|
+
children
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function splitString(string, separator, keepSeparator) {
|
|
137
|
+
if (!string) return [];
|
|
138
|
+
if (keepSeparator) {
|
|
139
|
+
const regex = separator instanceof RegExp ? new RegExp(`(${separator.source})`, separator.flags.includes("g") ? separator.flags : `${separator.flags}g`) : new RegExp(`(${escapeRegExp(separator)})`, "g");
|
|
140
|
+
return string.split(regex).filter((part) => part !== "");
|
|
141
|
+
}
|
|
142
|
+
return string.split(separator);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function escapeRegExp(str) {
|
|
146
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
147
|
+
}
|
|
148
|
+
|
|
124
149
|
function Match(_props) {
|
|
125
150
|
return null;
|
|
126
151
|
}
|
|
@@ -156,4 +181,4 @@ function Switch({ children, fallback = null }) {
|
|
|
156
181
|
return defaultContent;
|
|
157
182
|
}
|
|
158
183
|
|
|
159
|
-
export { Await, Default, Dynamic, ErrorBoundary, For, Match, QueryBoundary, Repeat, Show, Switch };
|
|
184
|
+
export { Await, Default, Dynamic, ErrorBoundary, For, Match, QueryBoundary, Repeat, Show, Split, Switch };
|
package/package.json
CHANGED