react-solidlike 2.5.1 → 2.5.3
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/dist/Await.d.ts +1 -1
- package/dist/ClientOnly.d.ts +1 -1
- package/dist/Dynamic.d.ts +1 -1
- package/dist/QueryBoundary.d.ts +3 -3
- package/dist/Show.d.ts +1 -1
- package/dist/Switch.d.ts +1 -1
- package/dist/Timeout.d.ts +1 -1
- package/dist/Visible.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +32 -10
- package/package.json +2 -2
package/dist/Await.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface AwaitProps<T> {
|
|
|
3
3
|
/** Promise to wait for | 要等待的 Promise */
|
|
4
4
|
promise: Promise<T> | T;
|
|
5
5
|
/** Content to show when Promise is pending | Promise pending 时显示的内容 */
|
|
6
|
-
loading?: ReactNode;
|
|
6
|
+
loading?: ReactNode | (() => ReactNode);
|
|
7
7
|
/** Content to show when Promise is rejected | Promise rejected 时显示的内容 */
|
|
8
8
|
error?: ReactNode | ((error: unknown) => ReactNode);
|
|
9
9
|
/** Content to render when Promise is fulfilled | Promise fulfilled 时渲染的内容 */
|
package/dist/ClientOnly.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface ClientOnlyProps {
|
|
|
3
3
|
/** Content to render only on client side | 仅在客户端渲染的内容 */
|
|
4
4
|
children: ReactNode | (() => ReactNode);
|
|
5
5
|
/** Fallback content during SSR | SSR 期间渲染的备选内容 */
|
|
6
|
-
fallback?: ReactNode;
|
|
6
|
+
fallback?: ReactNode | (() => ReactNode);
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Component that renders children only on the client side (after hydration)
|
package/dist/Dynamic.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type DynamicProps<T extends ElementType> = {
|
|
|
5
5
|
/** Component or element type to render | 要渲染的组件或元素类型 */
|
|
6
6
|
component: T | null | undefined | false;
|
|
7
7
|
/** Fallback content when component is falsy | 当 component 为 falsy 时渲染的备选内容 */
|
|
8
|
-
fallback?: ReactNode;
|
|
8
|
+
fallback?: ReactNode | (() => ReactNode);
|
|
9
9
|
} & PropsOf<T>;
|
|
10
10
|
/**
|
|
11
11
|
* Dynamic component rendering, selects component type based on conditions
|
package/dist/QueryBoundary.d.ts
CHANGED
|
@@ -14,11 +14,11 @@ export interface QueryBoundaryProps<T> {
|
|
|
14
14
|
/** Query result object, usually from @tanstack/react-query's useQuery | 查询结果对象,通常来自 @tanstack/react-query 的 useQuery */
|
|
15
15
|
query: QueryResult<T> | null | undefined;
|
|
16
16
|
/** Content to show while loading | 加载中时显示的内容 */
|
|
17
|
-
loading?: ReactNode;
|
|
17
|
+
loading?: ReactNode | (() => ReactNode);
|
|
18
18
|
/** Content to show when error occurs | 发生错误时显示的内容 */
|
|
19
|
-
error?: ReactNode;
|
|
19
|
+
error?: ReactNode | (() => ReactNode);
|
|
20
20
|
/** Content to show when data is empty | 数据为空时显示的内容 */
|
|
21
|
-
empty?: ReactNode;
|
|
21
|
+
empty?: ReactNode | (() => ReactNode);
|
|
22
22
|
/** Content to render on success, supports render props | 成功时渲染的内容,支持 render props 模式 */
|
|
23
23
|
children: ReactNode | ((data: T) => ReactNode);
|
|
24
24
|
/** Custom empty data check function, defaults to checking null/undefined or empty array | 自定义空数据判断函数,默认检查 data 是否为 null/undefined 或空数组 */
|
package/dist/Show.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface ShowProps<T> {
|
|
|
5
5
|
/** Content to render when condition is truthy | 条件为真时渲染的内容 */
|
|
6
6
|
children: ReactNode | ((value: NonNullable<T>) => ReactNode);
|
|
7
7
|
/** Fallback content when condition is falsy | 条件为假时渲染的备选内容 */
|
|
8
|
-
fallback?: ReactNode;
|
|
8
|
+
fallback?: ReactNode | (() => ReactNode);
|
|
9
9
|
/** Callback when condition is falsy (called before rendering fallback) | 条件为假时的回调(在渲染 fallback 之前调用) */
|
|
10
10
|
onFallback?: () => void;
|
|
11
11
|
}
|
package/dist/Switch.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface SwitchProps {
|
|
|
13
13
|
/** Match and Default components | Match 和 Default 组件 */
|
|
14
14
|
children: ReactNode;
|
|
15
15
|
/** Fallback content when no conditions match (can also use Default component) | 所有条件都不匹配时的备选内容(也可用 Default 组件) */
|
|
16
|
-
fallback?: ReactNode;
|
|
16
|
+
fallback?: ReactNode | (() => ReactNode);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Condition match component, used with Switch
|
package/dist/Timeout.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface TimeoutProps {
|
|
|
9
9
|
/** Display mode: 'after' = show after delay, 'before' = hide after delay | 显示模式:'after' = 延迟后显示,'before' = 延迟后隐藏 */
|
|
10
10
|
mode?: TimeoutMode;
|
|
11
11
|
/** Content to show when hidden (only for 'after' mode) | 隐藏时显示的内容(仅 'after' 模式) */
|
|
12
|
-
fallback?: ReactNode;
|
|
12
|
+
fallback?: ReactNode | (() => ReactNode);
|
|
13
13
|
/** Callback when timeout occurs | 超时发生时的回调 */
|
|
14
14
|
onTimeout?: () => void;
|
|
15
15
|
}
|
package/dist/Visible.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface VisibleProps {
|
|
|
3
3
|
/** Content to render when visible | 可见时渲染的内容 */
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
/** Fallback content before entering viewport | 进入视口前渲染的备选内容 */
|
|
6
|
-
fallback?: ReactNode;
|
|
6
|
+
fallback?: ReactNode | (() => ReactNode);
|
|
7
7
|
/** Root margin for intersection observer (e.g., "100px") | 交叉观察器的根边距 */
|
|
8
8
|
rootMargin?: string;
|
|
9
9
|
/** Visibility threshold (0-1) | 可见性阈值 */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { Await, type AwaitProps } from "./Await";
|
|
2
|
+
export { ClientOnly, type ClientOnlyProps } from "./ClientOnly";
|
|
2
3
|
export { Dynamic, type DynamicProps } from "./Dynamic";
|
|
3
4
|
export { ErrorBoundary, type ErrorBoundaryProps } from "./ErrorBoundary";
|
|
4
5
|
export { For, type ForProps } from "./For";
|
|
6
|
+
export { Once, type OnceProps } from "./Once";
|
|
5
7
|
export { QueryBoundary, type QueryBoundaryProps, type QueryResult } from "./QueryBoundary";
|
|
6
8
|
export { Repeat, type RepeatProps } from "./Repeat";
|
|
7
9
|
export { Show, type ShowProps } from "./Show";
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ function Await({ promise, loading = null, error = null, children }) {
|
|
|
34
34
|
cancelled = true;
|
|
35
35
|
};
|
|
36
36
|
}, [promise]);
|
|
37
|
-
if (state.status === "pending") return loading;
|
|
37
|
+
if (state.status === "pending") return typeof loading === "function" ? loading() : loading;
|
|
38
38
|
if (state.status === "rejected") {
|
|
39
39
|
if (typeof error === "function") return error(state.error);
|
|
40
40
|
return error;
|
|
@@ -43,8 +43,18 @@ function Await({ promise, loading = null, error = null, children }) {
|
|
|
43
43
|
return children;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function ClientOnly({ children, fallback = null }) {
|
|
47
|
+
const [isClient, setIsClient] = useState(false);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
setIsClient(true);
|
|
50
|
+
}, []);
|
|
51
|
+
if (!isClient) return typeof fallback === "function" ? fallback() : fallback;
|
|
52
|
+
if (typeof children === "function") return children();
|
|
53
|
+
return children;
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
function Dynamic({ component, fallback = null, ...props }) {
|
|
47
|
-
if (!component) return fallback;
|
|
57
|
+
if (!component) return typeof fallback === "function" ? fallback() : fallback;
|
|
48
58
|
return createElement(component, props);
|
|
49
59
|
}
|
|
50
60
|
|
|
@@ -88,6 +98,18 @@ function For({ each, children, keyExtractor, fallback = null, wrapper, reverse }
|
|
|
88
98
|
return wrapper && isValidElement(wrapper) ? cloneElement(wrapper, {}, elements) : elements;
|
|
89
99
|
}
|
|
90
100
|
|
|
101
|
+
function Once({ children }) {
|
|
102
|
+
const cachedRef = useRef({
|
|
103
|
+
rendered: false,
|
|
104
|
+
content: null
|
|
105
|
+
});
|
|
106
|
+
if (!cachedRef.current.rendered) {
|
|
107
|
+
cachedRef.current.rendered = true;
|
|
108
|
+
cachedRef.current.content = children;
|
|
109
|
+
}
|
|
110
|
+
return cachedRef.current.content;
|
|
111
|
+
}
|
|
112
|
+
|
|
91
113
|
function defaultIsEmpty(data) {
|
|
92
114
|
if (data == null) return true;
|
|
93
115
|
if (Array.isArray(data)) return data.length === 0;
|
|
@@ -98,9 +120,9 @@ function defaultIsEmpty(data) {
|
|
|
98
120
|
function QueryBoundary({ query, loading = null, error = null, empty = null, children, isEmptyFn = defaultIsEmpty }) {
|
|
99
121
|
if (!query) return null;
|
|
100
122
|
const { data, isPending, isError, isEmpty: queryIsEmpty } = query;
|
|
101
|
-
if (isPending) return loading;
|
|
102
|
-
if (isError && isEmptyFn(data)) return error;
|
|
103
|
-
if (queryIsEmpty ?? isEmptyFn(data)) return empty;
|
|
123
|
+
if (isPending) return typeof loading === "function" ? loading() : loading;
|
|
124
|
+
if (isError && isEmptyFn(data)) return typeof error === "function" ? error() : error;
|
|
125
|
+
if (queryIsEmpty ?? isEmptyFn(data)) return typeof empty === "function" ? empty() : empty;
|
|
104
126
|
if (typeof children === "function") return children(data);
|
|
105
127
|
return children;
|
|
106
128
|
}
|
|
@@ -117,7 +139,7 @@ function Repeat({ times, children, ...props }) {
|
|
|
117
139
|
function Show({ when, children, fallback = null, onFallback }) {
|
|
118
140
|
if (!when || isEmpty(when)) {
|
|
119
141
|
onFallback?.();
|
|
120
|
-
return fallback;
|
|
142
|
+
return typeof fallback === "function" ? fallback() : fallback;
|
|
121
143
|
}
|
|
122
144
|
if (typeof children === "function") return children(when);
|
|
123
145
|
return children;
|
|
@@ -169,7 +191,7 @@ function isDefaultElement(child) {
|
|
|
169
191
|
|
|
170
192
|
function Switch({ children, fallback = null }) {
|
|
171
193
|
const childArray = Children.toArray(children);
|
|
172
|
-
let defaultContent = fallback;
|
|
194
|
+
let defaultContent = typeof fallback === "function" ? fallback() : fallback;
|
|
173
195
|
for (const child of childArray) {
|
|
174
196
|
if (isDefaultElement(child)) {
|
|
175
197
|
defaultContent = child.props.children;
|
|
@@ -195,7 +217,7 @@ function Timeout({ ms, children, mode = "after", fallback = null, onTimeout }) {
|
|
|
195
217
|
}, ms);
|
|
196
218
|
return () => clearTimeout(timer);
|
|
197
219
|
}, [ms, onTimeout]);
|
|
198
|
-
if (mode === "after") return ready ? children : fallback;
|
|
220
|
+
if (mode === "after") return ready ? children : typeof fallback === "function" ? fallback() : fallback;
|
|
199
221
|
return ready ? children : null;
|
|
200
222
|
}
|
|
201
223
|
|
|
@@ -246,8 +268,8 @@ function Visible({ children, fallback = null, rootMargin = "0px", threshold = 0,
|
|
|
246
268
|
if (!isSupported) return children;
|
|
247
269
|
return /* @__PURE__ */ jsx("div", {
|
|
248
270
|
ref,
|
|
249
|
-
children: (once ? hasBeenVisible : isVisible) ? children : fallback
|
|
271
|
+
children: (once ? hasBeenVisible : isVisible) ? children : typeof fallback === "function" ? fallback() : fallback
|
|
250
272
|
});
|
|
251
273
|
}
|
|
252
274
|
|
|
253
|
-
export { Await, Default, Dynamic, ErrorBoundary, For, Match, QueryBoundary, Repeat, Show, Split, Switch, Timeout, Visible };
|
|
275
|
+
export { Await, ClientOnly, Default, Dynamic, ErrorBoundary, For, Match, Once, QueryBoundary, Repeat, Show, Split, Switch, Timeout, Visible };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-solidlike",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.3",
|
|
4
4
|
"description": "Declarative React control flow components inspired by Solid.js, replacing ternary expressions and array.map() in JSX",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@types/react-dom": "^19.2.3",
|
|
54
54
|
"react": "^19.2.3",
|
|
55
55
|
"react-dom": "^19.2.3",
|
|
56
|
-
"rolldown": "^1.0.0-rc.
|
|
56
|
+
"rolldown": "^1.0.0-rc.3",
|
|
57
57
|
"typescript": "^5.9.3"
|
|
58
58
|
}
|
|
59
59
|
}
|