@wwog/react 1.2.11 → 1.2.13

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
@@ -367,7 +367,7 @@ You can also use a container wrapper element:
367
367
 
368
368
  > Internal functions used by some components, which can also be used if needed
369
369
 
370
- #### `createExternalState` (v1.2.9+)
370
+ #### `createExternalState` (v1.2.9+, useGetter added in v1.2.13)
371
371
 
372
372
  A lightweight external state management utility that allows you to create and manage state outside the React component tree while maintaining perfect integration with components.
373
373
 
@@ -396,6 +396,13 @@ function ThemeConsumer() {
396
396
  </div>
397
397
  );
398
398
  }
399
+
400
+ // For read-only access (v1.2.13+)
401
+ function ReadOnlyThemeConsumer() {
402
+ const theme = themeState.useGetter();
403
+
404
+ return <div>Current theme is: {theme}</div>;
405
+ }
399
406
  ```
400
407
 
401
408
  - `createExternalState<T>(initialState, sideEffect?)`: Creates a state accessible outside components
@@ -405,6 +412,7 @@ function ThemeConsumer() {
405
412
  - `get()`: Get the current state value
406
413
  - `set(newState)`: Update the state value
407
414
  - `use()`: React Hook, returns `[state, setState]` for using this state in components
415
+ - `useGetter()`: React Hook that only returns the state value, useful when you only need to read the state
408
416
 
409
417
  Use cases:
410
418
 
package/dist/index.d.mts CHANGED
@@ -487,6 +487,11 @@ interface ExternalState<T> {
487
487
  * @returns Array containing current state and update function, similar to useState / 包含当前状态和更新函数的数组,类似于 useState
488
488
  */
489
489
  use: () => [T, (newState: T) => void];
490
+ /**
491
+ * @zh use的变体,只获取value.
492
+ * @en A variant of use that only gets the value.
493
+ */
494
+ useGetter: () => T;
490
495
  }
491
496
  interface ExternalWithKernel<T> extends ExternalState<T> {
492
497
  __listeners: CreateStateListener<T>[];
@@ -516,7 +521,7 @@ interface ExternalWithKernel<T> extends ExternalState<T> {
516
521
  * }
517
522
  * ```
518
523
  */
519
- declare function createExternalState<T>(initialState: T, sideEffect?: ExternalSideEffect<T>): ExternalState<T>;
524
+ declare function createExternalState<T>(initialState: T | (() => T), sideEffect?: ExternalSideEffect<T>): ExternalState<T>;
520
525
 
521
526
  /**
522
527
  * @description 性能优化,替代 React.Children.forEach, 回调可以返回 false 来中断循环
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import r,{useMemo as p,Children as J,Fragment as S,isValidElement as _,cloneElement as R,useEffect as W,useState as x,useCallback as H}from"react";function C(t,n){if(t===void 0)return;let e=0;if(Array.isArray(t)){for(const l of t)if(n(l,e++)===!1)break}else n(t,e)}const B=(t,n)=>t===n,E=t=>r.createElement(r.Fragment,null,t.children);E.displayName="Switch_Case";const w=t=>r.createElement(r.Fragment,null,t.children);w.displayName="Switch_Default";const y=t=>{const{value:n,compare:e=B,children:l,strict:o=!1}=t,a=new Set;let s=null,c=null,i=!1;return C(l,(d,u)=>{if(!r.isValidElement(d))throw new Error(`Switch Children only accepts valid React elements at index ${u}`);const m=d.type;if(m.displayName===E.displayName){const f=d.props;if(a.has(f.value))throw new Error(`Switch found duplicate Case value at index ${u}: ${JSON.stringify(f.value)}${o?" (detected in strict mode)":""}`);if(a.add(f.value),!s&&e(n,f.value)&&(s=f.children,o===!1))return!1}else if(m.displayName===w.displayName){if(i)throw new Error(`Switch can only have one Default child at index ${u}`);if(i=!0,c=d.props.children,!o&&s)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(m.displayName||m.name||m)} at index ${u}`)}),r.createElement(r.Fragment,null,s??c)};y.displayName="Switch",y.Case=E,y.Default=w,y.createTyped=function(){return{Switch:y,Case:E,Default:w}};const N=t=>r.createElement(r.Fragment,null,t.children),v=({children:t})=>r.createElement(r.Fragment,null,t),F=t=>r.createElement(r.Fragment,null,t.children);N.displayName="If_Then",v.displayName="If_Else",F.displayName="If_ElseIf";const h=({condition:t,children:n})=>{let e=null,l=null;const o=[];if(r.Children.forEach(n,a=>{if(!r.isValidElement(a))throw new Error("If component only accepts valid React elements");const s=a.type;if(s.displayName===N.displayName){if(e)throw new Error("If component can only have one Then child");e=a}else if(s.displayName===F.displayName)o.push(a);else if(s.displayName===v.displayName){if(l)throw new Error("If component can only have one Else child");l=a}else throw new Error(`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(s.displayName||s.name||s)}`)}),t)return e?r.createElement(r.Fragment,null,e.props.children):null;for(const a of o)if(a.props.condition)return r.createElement(r.Fragment,null,a.props.children);return l?r.createElement(r.Fragment,null,l.props.children):null};h.displayName="If",h.Then=N,h.ElseIf=F,h.Else=v,h.createTyped=function(){return{If:h,Then:N,ElseIf:F,Else:v}};const V=({condition:t,children:n})=>t?r.createElement(r.Fragment,null,n):null,Z=({condition:t,children:n})=>t===!1?r.createElement(r.Fragment,null,n):null,z=({all:t,any:n,none:e,children:l,fallback:o})=>p(()=>(t&&(n||e)&&console.warn('When: Multiple condition types (all, any, none) provided; "all" takes precedence.'),!!(t&&t.length>0&&t.every(Boolean)||n&&n.length>0&&n.some(Boolean)||e&&e.length>0&&e.every(a=>!a))),[t,n,e])?r.createElement(r.Fragment,null,l):r.createElement(r.Fragment,null,o||null),L=({data:t,transform:n,render:e,fallback:l})=>{const o=p(()=>n.reduce((a,s)=>s(a),t),[t,n]);return o==null?r.createElement(r.Fragment,null,l||null):r.createElement(r.Fragment,null,e(o))},q=t=>{const{children:n,h:e,w:l,size:o,height:a,width:s,className:c}=t;return r.createElement("div",{style:{width:o||l||s,height:o||e||a,flexShrink:0},className:c},n)},G=({let:t,props:n,children:e,fallback:l})=>{const o=p(()=>typeof t=="function"?t(n):t,[t,n]);return!e||!Object.keys(o).length?r.createElement(r.Fragment,null,l||null):r.createElement(r.Fragment,null,e(o))};function M(...t){const n=new Set;for(const e of t)if(e){if(typeof e=="string")n.add(e);else if(Array.isArray(e))e.forEach(l=>n.add(l));else if(typeof e=="object")for(const[l,o]of Object.entries(e))o&&n.add(l)}return Array.from(n).join(" ")}const K=t=>typeof t=="object"&&!!t,b=({className:t,children:n,asWrapper:e=!1})=>{if(!n)return null;if(J.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),r.createElement(S,null,n);if(!t)return r.createElement(S,null,n);const l=typeof t=="string"?t:M(...Object.values(t));if(e)return r.createElement(e===!0?"div":e,{className:l},n);if(_(n)){const o=n;let a=o?.props?.className;return o?.type?.displayName===b.displayName&&K(a)&&(a=M(...Object.values(a))),R(n,{className:M(l,a)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),r.createElement(S,null,n)};b.displayName="W/Styles";const Q=t=>{const{index:n=0,options:e,next:l,render:o}=t;W(()=>{if(e.length<n+1)throw new Error(`Index ${n} is out of bounds for options array of length ${e.length}. Defaulting to first option.`)},[n,e]);const[a,s]=x(n),c=()=>{s(i=>e.length?l?l(i,e):(i+1)%e.length:i)};return o(e[a],c)};function U(t){const{items:n,renderItem:e,filter:l}=t;return n?r.createElement(S,null,n.map((o,a)=>l&&!l(o)?null:e(o,a))):(console.error("ArrayRender: items is null"),null)}function X({source:t,format:n,children:e}){const l=p(()=>{if(t instanceof Date)return t;if(typeof t=="string"||typeof t=="number"){const a=new Date(t);return isNaN(a.getTime())?null:a}return null},[t]),o=p(()=>l?n?n(l):l.toLocaleString():null,[l,n]);return!o||!e?null:r.createElement(r.Fragment,null,e(o))}const $="onChange",ee="value";function te(t){const{defaultValue:n,onBeforeChange:e,trigger:l=$,valuePropName:o=ee,props:a}=t,s=Object.prototype.hasOwnProperty.call(a,o),[c,i]=x(n),d=s?a[o]:c,u=p(()=>a[l],[a,l]),m=H(f=>{const g=typeof f=="function"?f(d):f;e&&e(g,d)===!1||(s||i(g),u&&u(g))},[s,e,d,u]);return[d,m]}function ne(t,...n){try{const e=t(...n);return e instanceof Promise?e:Promise.resolve(e)}catch(e){return Promise.reject(e)}}const I=typeof Promise.try=="function"?Promise.try.bind(Promise):ne;function re(t,n){let e=t;const l=[],o=()=>e,a=s=>{const c=e;e=s,l.forEach(i=>i(e)),n&&I(n,e,c).catch(i=>{console.error("Error in external state side effect, Please do it within side effects:",i)})};return{get:o,set:a,use:()=>{const[s,c]=r.useState(e);return r.useEffect(()=>(l.push(c),()=>{const i=l.indexOf(c);i>-1&&l.splice(i,1)}),[]),[s,a]},__listeners:l}}function le(t,n){const e=n||new Date,l=e.getFullYear(),o=e.getMonth()+1,a=e.getDate(),s=e.getHours(),c=e.getMinutes(),i=e.getSeconds(),d=e.getMilliseconds(),u=e.getDay(),m=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],f=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],g=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],A=["January","February","March","April","May","June","July","August","September","October","November","December"],P=f[u],D=m[u],T=o-1,Y=A[T],k=g[T],O={YY:l.toString().slice(2),YYYY:l.toString(),M:o.toString(),MM:o.toString().padStart(2,"0"),MMM:k,MMMM:Y,D:a.toString(),DD:a.toString().padStart(2,"0"),d:u.toString(),dd:D,ddd:D,dddd:P,H:s.toString(),HH:s.toString().padStart(2,"0"),h:(s%12).toString(),hh:(s%12).toString().padStart(2,"0"),m:c.toString(),mm:c.toString().padStart(2,"0"),s:i.toString(),ss:i.toString().padStart(2,"0"),SSS:d.toString().padStart(3,"0"),Z:"+08:00",ZZ:"+0800",A:s<12?"AM":"PM",a:s<12?"am":"pm"};return t.replace(/YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|SSS|Z{1,2}|A|a/g,j=>O[j])}class ae{count=0;next(){return this.count++}}export{U as ArrayRender,ae as Counter,X as DateRender,Z as False,h as If,L as Pipe,G as Scope,q as SizeBox,b as Styles,y as Switch,Q as Toggle,V as True,z as When,C as childrenLoop,re as createExternalState,M as cx,le as formatDate,I as safePromiseTry,te as useControlled};
1
+ import r,{useMemo as h,Children as J,Fragment as S,isValidElement as _,cloneElement as R,useEffect as W,useState as x,useCallback as H}from"react";function C(t,n){if(t===void 0)return;let e=0;if(Array.isArray(t)){for(const l of t)if(n(l,e++)===!1)break}else n(t,e)}const B=(t,n)=>t===n,E=t=>r.createElement(r.Fragment,null,t.children);E.displayName="Switch_Case";const w=t=>r.createElement(r.Fragment,null,t.children);w.displayName="Switch_Default";const y=t=>{const{value:n,compare:e=B,children:l,strict:o=!1}=t,a=new Set;let s=null,i=null,u=!1;return C(l,(c,d)=>{if(!r.isValidElement(c))throw new Error(`Switch Children only accepts valid React elements at index ${d}`);const m=c.type;if(m.displayName===E.displayName){const f=c.props;if(a.has(f.value))throw new Error(`Switch found duplicate Case value at index ${d}: ${JSON.stringify(f.value)}${o?" (detected in strict mode)":""}`);if(a.add(f.value),!s&&e(n,f.value)&&(s=f.children,o===!1))return!1}else if(m.displayName===w.displayName){if(u)throw new Error(`Switch can only have one Default child at index ${d}`);if(u=!0,i=c.props.children,!o&&s)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(m.displayName||m.name||m)} at index ${d}`)}),r.createElement(r.Fragment,null,s??i)};y.displayName="Switch",y.Case=E,y.Default=w,y.createTyped=function(){return{Switch:y,Case:E,Default:w}};const N=t=>r.createElement(r.Fragment,null,t.children),v=({children:t})=>r.createElement(r.Fragment,null,t),F=t=>r.createElement(r.Fragment,null,t.children);N.displayName="If_Then",v.displayName="If_Else",F.displayName="If_ElseIf";const p=({condition:t,children:n})=>{let e=null,l=null;const o=[];if(r.Children.forEach(n,a=>{if(!r.isValidElement(a))throw new Error("If component only accepts valid React elements");const s=a.type;if(s.displayName===N.displayName){if(e)throw new Error("If component can only have one Then child");e=a}else if(s.displayName===F.displayName)o.push(a);else if(s.displayName===v.displayName){if(l)throw new Error("If component can only have one Else child");l=a}else throw new Error(`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(s.displayName||s.name||s)}`)}),t)return e?r.createElement(r.Fragment,null,e.props.children):null;for(const a of o)if(a.props.condition)return r.createElement(r.Fragment,null,a.props.children);return l?r.createElement(r.Fragment,null,l.props.children):null};p.displayName="If",p.Then=N,p.ElseIf=F,p.Else=v,p.createTyped=function(){return{If:p,Then:N,ElseIf:F,Else:v}};const V=({condition:t,children:n})=>t?r.createElement(r.Fragment,null,n):null,Z=({condition:t,children:n})=>t===!1?r.createElement(r.Fragment,null,n):null,z=({all:t,any:n,none:e,children:l,fallback:o})=>h(()=>(t&&(n||e)&&console.warn('When: Multiple condition types (all, any, none) provided; "all" takes precedence.'),!!(t&&t.length>0&&t.every(Boolean)||n&&n.length>0&&n.some(Boolean)||e&&e.length>0&&e.every(a=>!a))),[t,n,e])?r.createElement(r.Fragment,null,l):r.createElement(r.Fragment,null,o||null),L=({data:t,transform:n,render:e,fallback:l})=>{const o=h(()=>n.reduce((a,s)=>s(a),t),[t,n]);return o==null?r.createElement(r.Fragment,null,l||null):r.createElement(r.Fragment,null,e(o))},G=t=>{const{children:n,h:e,w:l,size:o,height:a,width:s,className:i}=t;return r.createElement("div",{style:{width:o||l||s,height:o||e||a,flexShrink:0},className:i},n)},q=({let:t,props:n,children:e,fallback:l})=>{const o=h(()=>typeof t=="function"?t(n):t,[t,n]);return!e||!Object.keys(o).length?r.createElement(r.Fragment,null,l||null):r.createElement(r.Fragment,null,e(o))};function M(...t){const n=new Set;for(const e of t)if(e){if(typeof e=="string")n.add(e);else if(Array.isArray(e))e.forEach(l=>n.add(l));else if(typeof e=="object")for(const[l,o]of Object.entries(e))o&&n.add(l)}return Array.from(n).join(" ")}const K=t=>typeof t=="object"&&!!t,b=({className:t,children:n,asWrapper:e=!1})=>{if(!n)return null;if(J.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),r.createElement(S,null,n);if(!t)return r.createElement(S,null,n);const l=typeof t=="string"?t:M(...Object.values(t));if(e)return r.createElement(e===!0?"div":e,{className:l},n);if(_(n)){const o=n;let a=o?.props?.className;return o?.type?.displayName===b.displayName&&K(a)&&(a=M(...Object.values(a))),R(n,{className:M(l,a)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),r.createElement(S,null,n)};b.displayName="W/Styles";const Q=t=>{const{index:n=0,options:e,next:l,render:o}=t;W(()=>{if(e.length<n+1)throw new Error(`Index ${n} is out of bounds for options array of length ${e.length}. Defaulting to first option.`)},[n,e]);const[a,s]=x(n),i=()=>{s(u=>e.length?l?l(u,e):(u+1)%e.length:u)};return o(e[a],i)};function U(t){const{items:n,renderItem:e,filter:l}=t;return n?r.createElement(S,null,n.map((o,a)=>l&&!l(o)?null:e(o,a))):(console.error("ArrayRender: items is null"),null)}function X({source:t,format:n,children:e}){const l=h(()=>{if(t instanceof Date)return t;if(typeof t=="string"||typeof t=="number"){const a=new Date(t);return isNaN(a.getTime())?null:a}return null},[t]),o=h(()=>l?n?n(l):l.toLocaleString():null,[l,n]);return!o||!e?null:r.createElement(r.Fragment,null,e(o))}const $="onChange",ee="value";function te(t){const{defaultValue:n,onBeforeChange:e,trigger:l=$,valuePropName:o=ee,props:a}=t,s=Object.prototype.hasOwnProperty.call(a,o),[i,u]=x(n),c=s?a[o]:i,d=h(()=>a[l],[a,l]),m=H(f=>{const g=typeof f=="function"?f(c):f;e&&e(g,c)===!1||(s||u(g),d&&d(g))},[s,e,c,d]);return[c,m]}function ne(t,...n){try{const e=t(...n);return e instanceof Promise?e:Promise.resolve(e)}catch(e){return Promise.reject(e)}}const I=typeof Promise.try=="function"?Promise.try.bind(Promise):ne;function re(t,n){let e=typeof t=="function"?t():t;const l=[],o=()=>e,a=i=>{const u=e;e=typeof i=="function"?i():i,l.forEach(c=>c(e)),n&&I(n,e,u).catch(c=>{console.error("Error in external state side effect, Please do it within side effects:",c)})},s=()=>{const[i,u]=r.useState(e);return r.useEffect(()=>(l.push(u),()=>{const c=l.indexOf(u);c>-1&&l.splice(c,1)}),[]),[i,a]};return{get:o,set:a,use:s,useGetter:()=>{const[i]=s();return i},__listeners:l}}function le(t,n){const e=n||new Date,l=e.getFullYear(),o=e.getMonth()+1,a=e.getDate(),s=e.getHours(),i=e.getMinutes(),u=e.getSeconds(),c=e.getMilliseconds(),d=e.getDay(),m=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],f=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],g=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],A=["January","February","March","April","May","June","July","August","September","October","November","December"],P=f[d],D=m[d],T=o-1,Y=A[T],k=g[T],O={YY:l.toString().slice(2),YYYY:l.toString(),M:o.toString(),MM:o.toString().padStart(2,"0"),MMM:k,MMMM:Y,D:a.toString(),DD:a.toString().padStart(2,"0"),d:d.toString(),dd:D,ddd:D,dddd:P,H:s.toString(),HH:s.toString().padStart(2,"0"),h:(s%12).toString(),hh:(s%12).toString().padStart(2,"0"),m:i.toString(),mm:i.toString().padStart(2,"0"),s:u.toString(),ss:u.toString().padStart(2,"0"),SSS:c.toString().padStart(3,"0"),Z:"+08:00",ZZ:"+0800",A:s<12?"AM":"PM",a:s<12?"am":"pm"};return t.replace(/YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|SSS|Z{1,2}|A|a/g,j=>O[j])}class ae{count=0;next(){return this.count++}}export{U as ArrayRender,ae as Counter,X as DateRender,Z as False,p as If,L as Pipe,q as Scope,G as SizeBox,b as Styles,y as Switch,Q as Toggle,V as True,z as When,C as childrenLoop,re as createExternalState,M as cx,le as formatDate,I as safePromiseTry,te as useControlled};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wwog/react",
3
- "version": "1.2.11",
3
+ "version": "1.2.13",
4
4
  "description": "A practical React component library providing declarative flow control and common UI utility components to make your React code more concise and readable.",
5
5
  "keywords": [
6
6
  "react",
@@ -46,6 +46,12 @@ export interface ExternalState<T> {
46
46
  * @returns Array containing current state and update function, similar to useState / 包含当前状态和更新函数的数组,类似于 useState
47
47
  */
48
48
  use: () => [T, (newState: T) => void];
49
+
50
+ /**
51
+ * @zh use的变体,只获取value.
52
+ * @en A variant of use that only gets the value.
53
+ */
54
+ useGetter: () => T;
49
55
  }
50
56
 
51
57
  export interface ExternalWithKernel<T> extends ExternalState<T> {
@@ -78,17 +84,21 @@ export interface ExternalWithKernel<T> extends ExternalState<T> {
78
84
  * ```
79
85
  */
80
86
  export function createExternalState<T>(
81
- initialState: T,
87
+ initialState: T | (() => T),
82
88
  sideEffect?: ExternalSideEffect<T>
83
89
  ): ExternalState<T> {
84
- let state: T = initialState;
90
+ let state: T =
91
+ typeof initialState === "function"
92
+ ? (initialState as () => T)()
93
+ : initialState;
94
+
85
95
  const listeners: CreateStateListener<T>[] = [];
86
96
 
87
97
  const get = () => state;
88
98
 
89
- const set = (newState: T) => {
99
+ const set = (newState: T | (() => T)) => {
90
100
  const prevState = state;
91
- state = newState;
101
+ state = typeof newState === "function" ? (newState as () => T)() : newState;
92
102
 
93
103
  listeners.forEach((listener) => listener(state));
94
104
  if (sideEffect) {
@@ -117,6 +127,11 @@ export function createExternalState<T>(
117
127
  return [localState, set] as [T, (newState: T) => void];
118
128
  };
119
129
 
130
+ const useGetter = () => {
131
+ const [value] = use();
132
+ return value;
133
+ };
134
+
120
135
  //@ts-expect-error ignore
121
- return { get, set, use, __listeners: listeners };
136
+ return { get, set, use, useGetter, __listeners: listeners };
122
137
  }