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 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 时渲染的内容 */
@@ -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
@@ -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.1",
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.2",
56
+ "rolldown": "^1.0.0-rc.3",
57
57
  "typescript": "^5.9.3"
58
58
  }
59
59
  }