@wwog/react 1.2.1 → 1.2.2

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.md CHANGED
@@ -150,17 +150,7 @@ function Example({ isActive }) {
150
150
  ```tsx
151
151
  import { Toggle } from "@wwog/react";
152
152
 
153
- interface ThemeChildProps {
154
- theme: string;
155
- toggleTheme: () => void;
156
- }
157
- const ThemeChild: React.FC<ThemeChildProps> = ({ theme, toggleTheme }) => (
158
- <div onClick={toggleTheme}>当前主题: {theme}</div>
159
- );
160
-
161
- <Toggle source="light" options={["light", "dark"]} target="theme" toggleTarget="toggleTheme">
162
- <ThemeChild />
163
- </Toggle>
153
+ <Toggle options={["light", "dark"]} render={(value,toggle)=>{/* xxx */}}/>
164
154
  ```
165
155
 
166
156
  - `options`:可切换的值数组。
@@ -168,7 +158,7 @@ const ThemeChild: React.FC<ThemeChildProps> = ({ theme, toggleTheme }) => (
168
158
  - `target`:传递切换值给子节点的属性名,默认 value。
169
159
  - `toggleTarget`:传递切换函数给子节点的属性名,默认 toggle。
170
160
  - `next`:自定义切换逻辑函数。
171
- - `children`:渲染内容。
161
+ - `render`:渲染函数。
172
162
 
173
163
  ### 通用组件
174
164
 
package/dist/index.d.mts CHANGED
@@ -202,18 +202,6 @@ interface ToggleProps<T = boolean> {
202
202
  * @description_zh 可切换的值数组。
203
203
  */
204
204
  options: T[];
205
- /**
206
- * @description_en The prop name to pass the toggled value to children.
207
- * @description_zh 将切换后的值传递给子节点的属性名。
208
- * @default 'value'
209
- */
210
- target?: string;
211
- /**
212
- * @description_en The prop name to pass the toggle function to children.
213
- * @description_zh 将切换函数传递给子节点的属性名。
214
- * @default 'toggle'
215
- */
216
- toggleTarget?: string;
217
205
  /**
218
206
  * @description_en Function to determine the next value index in the toggle sequence.
219
207
  * @description_zh 确定切换序列中下一个值索引的函数。
@@ -221,46 +209,26 @@ interface ToggleProps<T = boolean> {
221
209
  */
222
210
  next?: (curIndex: number, options: T[]) => number;
223
211
  /**
224
- * @description_en Content to render, receiving the toggled value and toggle function via the target and toggleTarget props.
225
- * @description_zh 渲染的内容,通过 target 和 toggleTarget 属性接收切换后的值和切换函数。
212
+ * @description_en Render function, receiving the toggled value and toggle function.
213
+ * @description_zh 渲染函数,接收切换后的值和切换函数。
226
214
  */
227
- children: ReactNode;
215
+ render: (value: T, toggle: () => void) => ReactNode;
228
216
  }
229
217
  /**
230
- * @description_zh 一个声明式组件,用于在预定义选项中切换值并通过指定属性传递给子组件,支持自定义切换逻辑。
231
- * @description_en A declarative component for toggling between predefined values and passing them to children via specified props, supporting custom toggle logic.
218
+ * @description_zh 一个声明式组件,用于在预定义选项中切换值并通过 render 函数传递给子组件,支持自定义切换逻辑。
219
+ * @description_en A declarative component for toggling between predefined values and passing them to children via a render function, supporting custom toggle logic.
232
220
  * @component
233
221
  * @example
234
222
  * ```tsx
235
- * interface ThemeChildProps {
236
- * theme: string;
237
- * toggleTheme: () => void;
238
- * }
239
- * const ThemeChild: FC<ThemeChildProps> = ({ theme, toggleTheme }) => (
240
- * <div onClick={toggleTheme}>当前主题: {theme}</div>
241
- * );
242
- *
243
- * <Toggle source="light" options={["light", "dark"]} target="theme" toggleTarget="toggleTheme">
244
- * <ThemeChild />
245
- * </Toggle>
246
- * ```
247
- *
248
- * @example
249
- * ```tsx
250
223
  * <Toggle
251
- * source={1}
252
- * options={[1, 2, 3]}
253
- * target="value"
254
- * toggleTarget="toggleValue"
255
- * next={(currentIndex, options) => {
256
- * return (currentIndex + 1) % options.length;
257
- * }}
258
- * >
259
- * <ValueChild />
260
- * </Toggle>
224
+ * options={["light", "dark"]}
225
+ * render={(theme, toggleTheme) => (
226
+ * <div onClick={toggleTheme}>当前主题: {theme}</div>
227
+ * )}
228
+ * />
261
229
  * ```
262
230
  */
263
- declare const Toggle: <T>(props: ToggleProps<T>) => (string | number | bigint | Iterable<React$1.ReactNode> | Promise<string | number | bigint | boolean | React$1.ReactPortal | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined> | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>>)[] | null | undefined;
231
+ declare const Toggle: <T>(props: ToggleProps<T>) => React$1.ReactNode;
264
232
 
265
233
  interface SizeBoxProps {
266
234
  size?: number | string;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import n,{useMemo as y,useEffect as C,useState as S,Fragment as T,useCallback as x}from"react";function I(e,l){if(e===void 0)return;let t=0;if(Array.isArray(e)){for(const a of e)if(l(a,t++)===!1)break}else l(e,t)}const $=(e,l)=>e===l,g=e=>n.createElement(n.Fragment,null,e.children);g.displayName="Switch_Case";const E=e=>n.createElement(n.Fragment,null,e.children);E.displayName="Switch_Default";const p=e=>{const{value:l,compare:t=$,children:a,strict:o=!1}=e,r=new Set;let i=null,u=null,h=!1;return I(a,(s,d)=>{if(!n.isValidElement(s))throw new Error(`Switch Children only accepts valid React elements at index ${d}`);const c=s.type;if(c.displayName===g.displayName){const m=s.props;if(r.has(m.value))throw new Error(`Switch found duplicate Case value at index ${d}: ${JSON.stringify(m.value)}${o?" (detected in strict mode)":""}`);if(r.add(m.value),!i&&t(l,m.value)&&(i=m.children,o===!1))return!1}else if(c.displayName===E.displayName){if(h)throw new Error(`Switch can only have one Default child at index ${d}`);if(h=!0,u=s.props.children,!o&&i)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(c.displayName||c.name||c)} at index ${d}`)}),n.createElement(n.Fragment,null,i??u)};p.displayName="Switch",p.Case=g,p.Default=E,p.createTyped=function(){return{Switch:p,Case:g,Default:E}};const w=e=>n.createElement(n.Fragment,null,e.children),N=({children:e})=>n.createElement(n.Fragment,null,e),v=e=>n.createElement(n.Fragment,null,e.children);w.displayName="If_Then",N.displayName="If_Else",v.displayName="If_ElseIf";const f=({condition:e,children:l})=>{let t=null,a=null;const o=[];if(n.Children.forEach(l,r=>{if(!n.isValidElement(r))throw new Error("If component only accepts valid React elements");const i=r.type;if(i.displayName===w.displayName){if(t)throw new Error("If component can only have one Then child");t=r}else if(i.displayName===v.displayName)o.push(r);else if(i.displayName===N.displayName){if(a)throw new Error("If component can only have one Else child");a=r}else throw new Error(`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(i.displayName||i.name||i)}`)}),e)return t?n.createElement(n.Fragment,null,t.props.children):null;for(const r of o)if(r.props.condition)return n.createElement(n.Fragment,null,r.props.children);return a?n.createElement(n.Fragment,null,a.props.children):null};f.displayName="If",f.Then=w,f.ElseIf=v,f.Else=N,f.createTyped=function(){return{If:f,Then:w,ElseIf:v,Else:N}};const b=({condition:e,children:l})=>e?n.createElement(n.Fragment,null,l):null,k=({condition:e,children:l})=>e===!1?n.createElement(n.Fragment,null,l):null,D=({all:e,any:l,none:t,children:a,fallback:o})=>y(()=>(e&&(l||t)&&console.warn('When: Multiple condition types (all, any, none) provided; "all" takes precedence.'),!!(e&&e.length>0&&e.every(Boolean)||l&&l.length>0&&l.some(Boolean)||t&&t.length>0&&t.every(r=>!r))),[e,l,t])?n.createElement(n.Fragment,null,a):n.createElement(n.Fragment,null,o||null),_=({data:e,transform:l,render:t,fallback:a})=>{const o=y(()=>l.reduce((r,i)=>i(r),e),[e,l]);return o==null?n.createElement(n.Fragment,null,a||null):n.createElement(n.Fragment,null,t(o))},A=e=>{const{index:l=0,options:t,target:a="value",toggleTarget:o="toggle",next:r,children:i}=e;C(()=>{if(t.length<l+1)throw new Error(`Index ${l} is out of bounds for options array of length ${t.length}. Defaulting to first option.`)},[l,t]);const[u,h]=S(l),s=()=>r?r(u,t):(u+1)%t.length,d=()=>{h(c=>t.length?s():c)};return n.Children.map(i,c=>n.isValidElement(c)?n.cloneElement(c,{[a]:u,[o]:d}):c)},B=e=>{const{children:l,h:t,w:a,size:o,height:r,width:i,className:u}=e;return n.createElement("div",{style:{width:o||a||i,height:o||t||r,flexShrink:0},className:u},l)};function O(e){const{items:l,renderItem:t,filter:a}=e;return l?n.createElement(T,null,l.map((o,r)=>a&&!a(o)?null:t(o,r))):(console.error("ArrayRender: items is null"),null)}const R=({let:e,props:l,children:t,fallback:a})=>{const o=y(()=>typeof e=="function"?e(l):e,[e,l]);return!t||!Object.keys(o).length?n.createElement(n.Fragment,null,a||null):n.createElement(n.Fragment,null,t(o))},V="onChange",P="value";function j(e){const{defaultValue:l,onBeforeChange:t,trigger:a=V,valuePropName:o=P,props:r}=e,i=Object.prototype.hasOwnProperty.call(r,o),[u,h]=S(l),s=i?r[o]:u,d=y(()=>r[a],[r,a]),c=x(m=>{const F=typeof m=="function"?m(s):m;t&&t(F,s)===!1||(i||h(F),d&&d(F))},[i,t,a,s,d]);return[s,c]}export{O as ArrayRender,k as False,f as If,_ as Pipe,R as Scope,B as SizeBox,p as Switch,A as Toggle,b as True,D as When,I as childrenLoop,j as useControlled};
1
+ import n,{useMemo as y,useEffect as C,useState as S,Fragment as x,useCallback as T}from"react";function I(e,l){if(e===void 0)return;let t=0;if(Array.isArray(e)){for(const r of e)if(l(r,t++)===!1)break}else l(e,t)}const b=(e,l)=>e===l,E=e=>n.createElement(n.Fragment,null,e.children);E.displayName="Switch_Case";const g=e=>n.createElement(n.Fragment,null,e.children);g.displayName="Switch_Default";const p=e=>{const{value:l,compare:t=b,children:r,strict:o=!1}=e,a=new Set;let i=null,u=null,d=!1;return I(r,(s,m)=>{if(!n.isValidElement(s))throw new Error(`Switch Children only accepts valid React elements at index ${m}`);const f=s.type;if(f.displayName===E.displayName){const c=s.props;if(a.has(c.value))throw new Error(`Switch found duplicate Case value at index ${m}: ${JSON.stringify(c.value)}${o?" (detected in strict mode)":""}`);if(a.add(c.value),!i&&t(l,c.value)&&(i=c.children,o===!1))return!1}else if(f.displayName===g.displayName){if(d)throw new Error(`Switch can only have one Default child at index ${m}`);if(d=!0,u=s.props.children,!o&&i)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(f.displayName||f.name||f)} at index ${m}`)}),n.createElement(n.Fragment,null,i??u)};p.displayName="Switch",p.Case=E,p.Default=g,p.createTyped=function(){return{Switch:p,Case:E,Default:g}};const w=e=>n.createElement(n.Fragment,null,e.children),N=({children:e})=>n.createElement(n.Fragment,null,e),v=e=>n.createElement(n.Fragment,null,e.children);w.displayName="If_Then",N.displayName="If_Else",v.displayName="If_ElseIf";const h=({condition:e,children:l})=>{let t=null,r=null;const o=[];if(n.Children.forEach(l,a=>{if(!n.isValidElement(a))throw new Error("If component only accepts valid React elements");const i=a.type;if(i.displayName===w.displayName){if(t)throw new Error("If component can only have one Then child");t=a}else if(i.displayName===v.displayName)o.push(a);else if(i.displayName===N.displayName){if(r)throw new Error("If component can only have one Else child");r=a}else throw new Error(`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(i.displayName||i.name||i)}`)}),e)return t?n.createElement(n.Fragment,null,t.props.children):null;for(const a of o)if(a.props.condition)return n.createElement(n.Fragment,null,a.props.children);return r?n.createElement(n.Fragment,null,r.props.children):null};h.displayName="If",h.Then=w,h.ElseIf=v,h.Else=N,h.createTyped=function(){return{If:h,Then:w,ElseIf:v,Else:N}};const k=({condition:e,children:l})=>e?n.createElement(n.Fragment,null,l):null,$=({condition:e,children:l})=>e===!1?n.createElement(n.Fragment,null,l):null,D=({all:e,any:l,none:t,children:r,fallback:o})=>y(()=>(e&&(l||t)&&console.warn('When: Multiple condition types (all, any, none) provided; "all" takes precedence.'),!!(e&&e.length>0&&e.every(Boolean)||l&&l.length>0&&l.some(Boolean)||t&&t.length>0&&t.every(a=>!a))),[e,l,t])?n.createElement(n.Fragment,null,r):n.createElement(n.Fragment,null,o||null),_=({data:e,transform:l,render:t,fallback:r})=>{const o=y(()=>l.reduce((a,i)=>i(a),e),[e,l]);return o==null?n.createElement(n.Fragment,null,r||null):n.createElement(n.Fragment,null,t(o))},A=e=>{const{index:l=0,options:t,next:r,render:o}=e;C(()=>{if(t.length<l+1)throw new Error(`Index ${l} is out of bounds for options array of length ${t.length}. Defaulting to first option.`)},[l,t]);const[a,i]=S(l),u=()=>{i(d=>t.length?r?r(d,t):(d+1)%t.length:d)};return o(t[a],u)},B=e=>{const{children:l,h:t,w:r,size:o,height:a,width:i,className:u}=e;return n.createElement("div",{style:{width:o||r||i,height:o||t||a,flexShrink:0},className:u},l)};function O(e){const{items:l,renderItem:t,filter:r}=e;return l?n.createElement(x,null,l.map((o,a)=>r&&!r(o)?null:t(o,a))):(console.error("ArrayRender: items is null"),null)}const R=({let:e,props:l,children:t,fallback:r})=>{const o=y(()=>typeof e=="function"?e(l):e,[e,l]);return!t||!Object.keys(o).length?n.createElement(n.Fragment,null,r||null):n.createElement(n.Fragment,null,t(o))},P="onChange",V="value";function j(e){const{defaultValue:l,onBeforeChange:t,trigger:r=P,valuePropName:o=V,props:a}=e,i=Object.prototype.hasOwnProperty.call(a,o),[u,d]=S(l),s=i?a[o]:u,m=y(()=>a[r],[a,r]),f=T(c=>{const F=typeof c=="function"?c(s):c;t&&t(F,s)===!1||(i||d(F),m&&m(F))},[i,t,r,s,m]);return[s,f]}export{O as ArrayRender,$ as False,h as If,_ as Pipe,R as Scope,B as SizeBox,p as Switch,A as Toggle,k as True,D as When,I as childrenLoop,j as useControlled};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wwog/react",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "author": "wwog",
@@ -1,4 +1,4 @@
1
- import React, { ReactNode, useState, useMemo, useEffect } from "react";
1
+ import React, { useState, useEffect, ReactNode } from "react";
2
2
 
3
3
  export interface ToggleProps<T = boolean> {
4
4
  /**
@@ -12,18 +12,6 @@ export interface ToggleProps<T = boolean> {
12
12
  * @description_zh 可切换的值数组。
13
13
  */
14
14
  options: T[];
15
- /**
16
- * @description_en The prop name to pass the toggled value to children.
17
- * @description_zh 将切换后的值传递给子节点的属性名。
18
- * @default 'value'
19
- */
20
- target?: string;
21
- /**
22
- * @description_en The prop name to pass the toggle function to children.
23
- * @description_zh 将切换函数传递给子节点的属性名。
24
- * @default 'toggle'
25
- */
26
- toggleTarget?: string;
27
15
  /**
28
16
  * @description_en Function to determine the next value index in the toggle sequence.
29
17
  * @description_zh 确定切换序列中下一个值索引的函数。
@@ -31,54 +19,32 @@ export interface ToggleProps<T = boolean> {
31
19
  */
32
20
  next?: (curIndex: number, options: T[]) => number;
33
21
  /**
34
- * @description_en Content to render, receiving the toggled value and toggle function via the target and toggleTarget props.
35
- * @description_zh 渲染的内容,通过 target 和 toggleTarget 属性接收切换后的值和切换函数。
22
+ * @description_en Render function, receiving the toggled value and toggle function.
23
+ * @description_zh 渲染函数,接收切换后的值和切换函数。
36
24
  */
37
- children: ReactNode;
25
+ render: (value: T, toggle: () => void) => ReactNode;
38
26
  }
39
27
 
40
28
  /**
41
- * @description_zh 一个声明式组件,用于在预定义选项中切换值并通过指定属性传递给子组件,支持自定义切换逻辑。
42
- * @description_en A declarative component for toggling between predefined values and passing them to children via specified props, supporting custom toggle logic.
29
+ * @description_zh 一个声明式组件,用于在预定义选项中切换值并通过 render 函数传递给子组件,支持自定义切换逻辑。
30
+ * @description_en A declarative component for toggling between predefined values and passing them to children via a render function, supporting custom toggle logic.
43
31
  * @component
44
32
  * @example
45
33
  * ```tsx
46
- * interface ThemeChildProps {
47
- * theme: string;
48
- * toggleTheme: () => void;
49
- * }
50
- * const ThemeChild: FC<ThemeChildProps> = ({ theme, toggleTheme }) => (
51
- * <div onClick={toggleTheme}>当前主题: {theme}</div>
52
- * );
53
- *
54
- * <Toggle source="light" options={["light", "dark"]} target="theme" toggleTarget="toggleTheme">
55
- * <ThemeChild />
56
- * </Toggle>
57
- * ```
58
- *
59
- * @example
60
- * ```tsx
61
34
  * <Toggle
62
- * source={1}
63
- * options={[1, 2, 3]}
64
- * target="value"
65
- * toggleTarget="toggleValue"
66
- * next={(currentIndex, options) => {
67
- * return (currentIndex + 1) % options.length;
68
- * }}
69
- * >
70
- * <ValueChild />
71
- * </Toggle>
35
+ * options={["light", "dark"]}
36
+ * render={(theme, toggleTheme) => (
37
+ * <div onClick={toggleTheme}>当前主题: {theme}</div>
38
+ * )}
39
+ * />
72
40
  * ```
73
41
  */
74
42
  export const Toggle = <T,>(props: ToggleProps<T>) => {
75
43
  const {
76
44
  index = 0,
77
45
  options,
78
- target = "value",
79
- toggleTarget = "toggle",
80
46
  next,
81
- children,
47
+ render,
82
48
  } = props;
83
49
 
84
50
  useEffect(() => {
@@ -90,27 +56,12 @@ export const Toggle = <T,>(props: ToggleProps<T>) => {
90
56
  }, [index, options]);
91
57
 
92
58
  const [curIndex, setCurIndex] = useState<number>(index);
93
- const nextIndex = () => {
94
- if (next) {
95
- return next(curIndex, options);
96
- }
97
- return (curIndex + 1) % options.length;
98
- };
99
-
100
59
  const toggle = () => {
101
60
  setCurIndex((prev) => {
102
61
  if (!options.length) return prev;
103
- return nextIndex();
62
+ return next ? next(prev, options) : (prev + 1) % options.length;
104
63
  });
105
64
  };
106
65
 
107
- return React.Children.map(children, (child) => {
108
- if (React.isValidElement(child)) {
109
- return React.cloneElement(child, {
110
- [target]: curIndex,
111
- [toggleTarget]: toggle,
112
- } as { [key: string]: any });
113
- }
114
- return child;
115
- });
66
+ return render(options[curIndex], toggle);
116
67
  };