react-solidlike 2.5.3 → 2.5.4

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.
@@ -13,6 +13,8 @@ export interface QueryResult<T> {
13
13
  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
+ /** When false, renders nothing directly | 为 false 时直接不渲染任何内容 */
17
+ when?: boolean;
16
18
  /** Content to show while loading | 加载中时显示的内容 */
17
19
  loading?: ReactNode | (() => ReactNode);
18
20
  /** Content to show when error occurs | 发生错误时显示的内容 */
@@ -57,4 +59,4 @@ export interface QueryBoundaryProps<T> {
57
59
  * {(data) => <ItemList items={data.items} />}
58
60
  * </QueryBoundary>
59
61
  */
60
- export declare function QueryBoundary<T>({ query, loading, error, empty, children, isEmptyFn, }: QueryBoundaryProps<T>): ReactNode;
62
+ export declare function QueryBoundary<T>({ query, when, loading, error, empty, children, isEmptyFn, }: QueryBoundaryProps<T>): ReactNode;
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { Children, Component, Fragment, cloneElement, createElement, isValidElement, useEffect, useRef, useState } from "react";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
 
4
+ function resolveNode(node) {
5
+ return typeof node === "function" ? node() : node;
6
+ }
7
+
4
8
  function Await({ promise, loading = null, error = null, children }) {
5
9
  const [state, setState] = useState(() => {
6
10
  if (!(promise instanceof Promise)) return {
@@ -34,11 +38,8 @@ function Await({ promise, loading = null, error = null, children }) {
34
38
  cancelled = true;
35
39
  };
36
40
  }, [promise]);
37
- if (state.status === "pending") return typeof loading === "function" ? loading() : loading;
38
- if (state.status === "rejected") {
39
- if (typeof error === "function") return error(state.error);
40
- return error;
41
- }
41
+ if (state.status === "pending") return resolveNode(loading);
42
+ if (state.status === "rejected") return typeof error === "function" ? error(state.error) : error;
42
43
  if (typeof children === "function") return children(state.value);
43
44
  return children;
44
45
  }
@@ -48,13 +49,13 @@ function ClientOnly({ children, fallback = null }) {
48
49
  useEffect(() => {
49
50
  setIsClient(true);
50
51
  }, []);
51
- if (!isClient) return typeof fallback === "function" ? fallback() : fallback;
52
+ if (!isClient) return resolveNode(fallback);
52
53
  if (typeof children === "function") return children();
53
54
  return children;
54
55
  }
55
56
 
56
57
  function Dynamic({ component, fallback = null, ...props }) {
57
- if (!component) return typeof fallback === "function" ? fallback() : fallback;
58
+ if (!component) return resolveNode(fallback);
58
59
  return createElement(component, props);
59
60
  }
60
61
 
@@ -117,12 +118,12 @@ function defaultIsEmpty(data) {
117
118
  return false;
118
119
  }
119
120
 
120
- function QueryBoundary({ query, loading = null, error = null, empty = null, children, isEmptyFn = defaultIsEmpty }) {
121
- if (!query) return null;
121
+ function QueryBoundary({ query, when = true, loading = null, error = null, empty = null, children, isEmptyFn = defaultIsEmpty }) {
122
+ if (!when || !query) return null;
122
123
  const { data, isPending, isError, isEmpty: queryIsEmpty } = query;
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;
124
+ if (isPending) return resolveNode(loading);
125
+ if (isError && isEmptyFn(data)) return resolveNode(error);
126
+ if (queryIsEmpty ?? isEmptyFn(data)) return resolveNode(empty);
126
127
  if (typeof children === "function") return children(data);
127
128
  return children;
128
129
  }
@@ -139,7 +140,7 @@ function Repeat({ times, children, ...props }) {
139
140
  function Show({ when, children, fallback = null, onFallback }) {
140
141
  if (!when || isEmpty(when)) {
141
142
  onFallback?.();
142
- return typeof fallback === "function" ? fallback() : fallback;
143
+ return resolveNode(fallback);
143
144
  }
144
145
  if (typeof children === "function") return children(when);
145
146
  return children;
@@ -191,7 +192,7 @@ function isDefaultElement(child) {
191
192
 
192
193
  function Switch({ children, fallback = null }) {
193
194
  const childArray = Children.toArray(children);
194
- let defaultContent = typeof fallback === "function" ? fallback() : fallback;
195
+ let defaultContent = resolveNode(fallback);
195
196
  for (const child of childArray) {
196
197
  if (isDefaultElement(child)) {
197
198
  defaultContent = child.props.children;
@@ -217,7 +218,7 @@ function Timeout({ ms, children, mode = "after", fallback = null, onTimeout }) {
217
218
  }, ms);
218
219
  return () => clearTimeout(timer);
219
220
  }, [ms, onTimeout]);
220
- if (mode === "after") return ready ? children : typeof fallback === "function" ? fallback() : fallback;
221
+ if (mode === "after") return ready ? children : resolveNode(fallback);
221
222
  return ready ? children : null;
222
223
  }
223
224
 
@@ -268,7 +269,7 @@ function Visible({ children, fallback = null, rootMargin = "0px", threshold = 0,
268
269
  if (!isSupported) return children;
269
270
  return /* @__PURE__ */ jsx("div", {
270
271
  ref,
271
- children: (once ? hasBeenVisible : isVisible) ? children : typeof fallback === "function" ? fallback() : fallback
272
+ children: (once ? hasBeenVisible : isVisible) ? children : resolveNode(fallback)
272
273
  });
273
274
  }
274
275
 
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from "react";
2
+ /** Node that can be either a ReactNode or a function returning a ReactNode | 可以是 ReactNode 或返回 ReactNode 的函数 */
3
+ export type ResolvableNode = ReactNode | (() => ReactNode);
4
+ /** Resolve a node that may be a function into a ReactNode | 将可能是函数的节点解析为 ReactNode */
5
+ export declare function resolveNode(node: ResolvableNode): ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-solidlike",
3
- "version": "2.5.3",
3
+ "version": "2.5.4",
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",