@wwog/react
Advanced tools
Comparing version
@@ -1,1 +0,1 @@ | ||
import a,{useMemo as y,Children as _,Fragment as E,isValidElement as W,cloneElement as H,useEffect as I,useState as A,useRef as x,useCallback as B}from"react";function P(t,n){if(t===void 0)return;let e=0;if(Array.isArray(t)){for(const r of t)if(n(r,e++)===!1)break}else n(t,e)}const V=(t,n)=>t===n,w=t=>a.createElement(a.Fragment,null,t.children);w.displayName="Switch_Case";const N=t=>a.createElement(a.Fragment,null,t.children);N.displayName="Switch_Default";const g=t=>{const{value:n,compare:e=V,children:r,strict:o=!1}=t,l=new Set;let s=null,f=null,m=!1;return P(r,(c,i)=>{if(!a.isValidElement(c))throw new Error(`Switch Children only accepts valid React elements at index ${i}`);const u=c.type;if(u.displayName===w.displayName){const d=c.props;if(l.has(d.value))throw new Error(`Switch found duplicate Case value at index ${i}: ${JSON.stringify(d.value)}${o?" (detected in strict mode)":""}`);if(l.add(d.value),!s&&e(n,d.value)&&(s=d.children,o===!1))return!1}else if(u.displayName===N.displayName){if(m)throw new Error(`Switch can only have one Default child at index ${i}`);if(m=!0,f=c.props.children,!o&&s)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(u.displayName||u.name||u)} at index ${i}`)}),a.createElement(a.Fragment,null,s??f)};g.displayName="Switch",g.Case=w,g.Default=N,g.createTyped=function(){return{Switch:g,Case:w,Default:N}};const v=t=>a.createElement(a.Fragment,null,t.children),b=({children:t})=>a.createElement(a.Fragment,null,t),M=t=>a.createElement(a.Fragment,null,t.children);v.displayName="If_Then",b.displayName="If_Else",M.displayName="If_ElseIf";const p=({condition:t,children:n})=>{let e=null,r=null;const o=[];if(a.Children.forEach(n,l=>{if(!a.isValidElement(l))throw new Error("If component only accepts valid React elements");const s=l.type;if(s.displayName===v.displayName){if(e)throw new Error("If component can only have one Then child");e=l}else if(s.displayName===M.displayName)o.push(l);else if(s.displayName===b.displayName){if(r)throw new Error("If component can only have one Else child");r=l}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?a.createElement(a.Fragment,null,e.props.children):null;for(const l of o)if(l.props.condition)return a.createElement(a.Fragment,null,l.props.children);return r?a.createElement(a.Fragment,null,r.props.children):null};p.displayName="If",p.Then=v,p.ElseIf=M,p.Else=b,p.createTyped=function(){return{If:p,Then:v,ElseIf:M,Else:b}};const Z=({condition:t,children:n})=>t?a.createElement(a.Fragment,null,n):null,z=({condition:t,children:n})=>t===!1?a.createElement(a.Fragment,null,n):null,L=({all:t,any:n,none:e,children:r,fallback:o})=>y(()=>(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(l=>!l))),[t,n,e])?a.createElement(a.Fragment,null,r):a.createElement(a.Fragment,null,o||null),G=({data:t,transform:n,render:e,fallback:r})=>{const o=y(()=>n.reduce((l,s)=>s(l),t),[t,n]);return o==null?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,e(o))},U=t=>{const{children:n,h:e,w:r,size:o,height:l,width:s,className:f}=t;return a.createElement("div",{style:{width:o||r||s,height:o||e||l,flexShrink:0},className:f},n)},q=({let:t,props:n,children:e,fallback:r})=>{const o=y(()=>typeof t=="function"?t(n):t,[t,n]);return!e||!Object.keys(o).length?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,e(o))};function F(...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(r=>n.add(r));else if(typeof e=="object")for(const[r,o]of Object.entries(e))o&&n.add(r)}return Array.from(n).join(" ")}const K=t=>typeof t=="object"&&!!t,T=({className:t,children:n,asWrapper:e=!1})=>{if(!n)return null;if(_.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),a.createElement(E,null,n);if(!t)return a.createElement(E,null,n);const r=typeof t=="string"?t:F(...Object.values(t));if(e)return a.createElement(e===!0?"div":e,{className:r},n);if(W(n)){const o=n;let l=o?.props?.className;return o?.type?.displayName===T.displayName&&K(l)&&(l=F(...Object.values(l))),H(n,{className:F(r,l)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),a.createElement(E,null,n)};T.displayName="W/Styles";const Q=t=>{const{index:n=0,options:e,next:r,render:o}=t;I(()=>{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[l,s]=A(n),f=()=>{s(m=>e.length?r?r(m,e):(m+1)%e.length:m)};return o(e[l],f)},X=({onIntersect:t,threshold:n=.1,root:e=null,rootMargin:r="0px",triggerOnce:o=!1,disabled:l=!1,children:s,className:f,style:m})=>{const c=x(null),i=x(null),u=x(!1);return I(()=>{if(l||!c.current)return;if(!window.IntersectionObserver){console.warn("IntersectionObserver is not supported in this browser");return}const d=c.current,h=D=>{D.forEach(S=>{if(S.isIntersecting){if(o&&u.current)return;t(S,i.current),o&&(u.current=!0,i.current?.unobserve(d))}})};return i.current=new IntersectionObserver(h,{root:e,rootMargin:r,threshold:n}),i.current.observe(d),()=>{i.current&&i.current.disconnect()}},[t,n,e,r,o,l]),I(()=>{o||(u.current=!1)},[o]),a.createElement("div",{ref:c,className:f,style:m},s)};function $(t){const{items:n,renderItem:e,filter:r}=t;return n?a.createElement(E,null,n.map((o,l)=>r&&!r(o)?null:e(o,l))):(console.error("ArrayRender: items is null"),null)}function ee({source:t,format:n,children:e}){const r=y(()=>{if(t instanceof Date)return t;if(typeof t=="string"||typeof t=="number"){const l=new Date(t);return isNaN(l.getTime())?null:l}return null},[t]),o=y(()=>r?n?n(r):r.toLocaleString():null,[r,n]);return!o||!e?null:a.createElement(a.Fragment,null,e(o))}const te="onChange",ne="value";function re(t){const{defaultValue:n,onBeforeChange:e,trigger:r=te,valuePropName:o=ne,props:l}=t,s=Object.prototype.hasOwnProperty.call(l,o),[f,m]=A(n),c=s?l[o]:f,i=y(()=>l[r],[l,r]),u=B(d=>{const h=typeof d=="function"?d(c):d;e&&e(h,c)===!1||(s||m(h),i&&i(h))},[s,e,c,i]);return[c,u]}function le(t,...n){try{const e=t(...n);return e instanceof Promise?e:Promise.resolve(e)}catch(e){return Promise.reject(e)}}const Y=typeof Promise.try=="function"?Promise.try.bind(Promise):le;function ae(t,n={}){let e=typeof t=="function"?t():t;const r=[],{sideEffect:o,transform:l}=n,s=()=>{const c=e;return l?.get?l.get(c):c},f=c=>{const i=e,u=l?.get?l.get(i):i;e=l?.set?l.set(typeof c=="function"?c(u):c):typeof c=="function"?c(u):c,r.forEach(d=>d(e)),o&&Y(o,e,i).catch(d=>{console.error("Error in external state side effect, Please do it within side effects:",d)})},m=()=>{const[c,i]=a.useState(e);return a.useEffect(()=>(r.push(i),()=>{const u=r.indexOf(i);u>-1&&r.splice(u,1)}),[]),[l?.get?l.get(c):c,f]};return{get:s,set:f,use:m,useGetter:()=>{const[c]=m();return c},__listeners:r}}function oe(t,n){const e=n||new Date,r=e.getFullYear(),o=e.getMonth()+1,l=e.getDate(),s=e.getHours(),f=e.getMinutes(),m=e.getSeconds(),c=e.getMilliseconds(),i=e.getDay(),u=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],d=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],D=["January","February","March","April","May","June","July","August","September","October","November","December"],S=d[i],C=u[i],O=o-1,k=D[O],j=h[O],J={YY:r.toString().slice(2),YYYY:r.toString(),M:o.toString(),MM:o.toString().padStart(2,"0"),MMM:j,MMMM:k,D:l.toString(),DD:l.toString().padStart(2,"0"),d:i.toString(),dd:C,ddd:C,dddd:S,H:s.toString(),HH:s.toString().padStart(2,"0"),h:(s%12).toString(),hh:(s%12).toString().padStart(2,"0"),m:f.toString(),mm:f.toString().padStart(2,"0"),s:m.toString(),ss:m.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,R=>J[R])}class se{count=0;next(){return this.count++}}export{$ as ArrayRender,se as Counter,ee as DateRender,z as False,p as If,X as Observer,G as Pipe,q as Scope,U as SizeBox,T as Styles,g as Switch,Q as Toggle,Z as True,L as When,P as childrenLoop,ae as createExternalState,F as cx,oe as formatDate,Y as safePromiseTry,re as useControlled}; | ||
import a,{useMemo as g,Children as W,Fragment as E,isValidElement as H,cloneElement as B,useEffect as D,useState as A,useRef as O,useCallback as V}from"react";function P(e,n){if(e===void 0)return;let t=0;if(Array.isArray(e)){for(const r of e)if(n(r,t++)===!1)break}else n(e,t)}const Z=(e,n)=>e===n,w=e=>a.createElement(a.Fragment,null,e.children);w.displayName="Switch_Case";const N=e=>a.createElement(a.Fragment,null,e.children);N.displayName="Switch_Default";const y=e=>{const{value:n,compare:t=Z,children:r,strict:o=!1}=e,l=new Set;let s=null,u=null,f=!1;return P(r,(c,i)=>{if(!a.isValidElement(c))throw new Error(`Switch Children only accepts valid React elements at index ${i}`);const d=c.type;if(d.displayName===w.displayName){const m=c.props;if(l.has(m.value))throw new Error(`Switch found duplicate Case value at index ${i}: ${JSON.stringify(m.value)}${o?" (detected in strict mode)":""}`);if(l.add(m.value),!s&&t(n,m.value)&&(s=m.children,o===!1))return!1}else if(d.displayName===N.displayName){if(f)throw new Error(`Switch can only have one Default child at index ${i}`);if(f=!0,u=c.props.children,!o&&s)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(d.displayName||d.name||d)} at index ${i}`)}),a.createElement(a.Fragment,null,s??u)};y.displayName="Switch",y.Case=w,y.Default=N,y.createTyped=function(){return{Switch:y,Case:w,Default:N}};const v=e=>a.createElement(a.Fragment,null,e.children),b=({children:e})=>a.createElement(a.Fragment,null,e),M=e=>a.createElement(a.Fragment,null,e.children);v.displayName="If_Then",b.displayName="If_Else",M.displayName="If_ElseIf";const h=({condition:e,children:n})=>{let t=null,r=null;const o=[];if(a.Children.forEach(n,l=>{if(!a.isValidElement(l))throw new Error("If component only accepts valid React elements");const s=l.type;if(s.displayName===v.displayName){if(t)throw new Error("If component can only have one Then child");t=l}else if(s.displayName===M.displayName)o.push(l);else if(s.displayName===b.displayName){if(r)throw new Error("If component can only have one Else child");r=l}else throw new Error(`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(s.displayName||s.name||s)}`)}),e)return t?a.createElement(a.Fragment,null,t.props.children):null;for(const l of o)if(l.props.condition)return a.createElement(a.Fragment,null,l.props.children);return r?a.createElement(a.Fragment,null,r.props.children):null};h.displayName="If",h.Then=v,h.ElseIf=M,h.Else=b,h.createTyped=function(){return{If:h,Then:v,ElseIf:M,Else:b}};const z=({condition:e,children:n})=>e?a.createElement(a.Fragment,null,n):null,L=({condition:e,children:n})=>e===!1?a.createElement(a.Fragment,null,n):null,U=({all:e,any:n,none:t,children:r,fallback:o})=>g(()=>(e&&(n||t)&&console.warn('When: Multiple condition types (all, any, none) provided; "all" takes precedence.'),!!(e&&e.length>0&&e.every(Boolean)||n&&n.length>0&&n.some(Boolean)||t&&t.length>0&&t.every(l=>!l))),[e,n,t])?a.createElement(a.Fragment,null,r):a.createElement(a.Fragment,null,o||null),G=({data:e,transform:n,render:t,fallback:r})=>{const o=g(()=>n.reduce((l,s)=>s(l),e),[e,n]);return o==null?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,t(o))},$=e=>{const{children:n,h:t,w:r,size:o,height:l,width:s,className:u}=e;return a.createElement("div",{style:{width:o||r||s,height:o||t||l,flexShrink:0},className:u},n)},q=({let:e,props:n,children:t,fallback:r})=>{const o=g(()=>typeof e=="function"?e(n):e,[e,n]);return!t||!Object.keys(o).length?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,t(o))};function F(...e){const n=new Set;for(const t of e)if(t){if(typeof t=="string")n.add(t);else if(Array.isArray(t))t.forEach(r=>n.add(r));else if(typeof t=="object")for(const[r,o]of Object.entries(t))o&&n.add(r)}return Array.from(n).join(" ")}const K=e=>typeof e=="object"&&!!e,x=({className:e,children:n,asWrapper:t=!1})=>{if(!n)return null;if(W.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),a.createElement(E,null,n);if(!e)return a.createElement(E,null,n);const r=typeof e=="string"?e:F(...Object.values(e));if(t)return a.createElement(t===!0?"div":t,{className:r},n);if(H(n)){const o=n;let l=o?.props?.className;return o?.type?.displayName===x.displayName&&K(l)&&(l=F(...Object.values(l))),B(n,{className:F(r,l)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),a.createElement(E,null,n)};x.displayName="W/Styles";const Q=e=>{const{index:n=0,options:t,next:r,render:o}=e;D(()=>{if(t.length<n+1)throw new Error(`Index ${n} is out of bounds for options array of length ${t.length}. Defaulting to first option.`)},[n,t]);const[l,s]=A(n),u=()=>{s(f=>t.length?r?r(f,t):(f+1)%t.length:f)};return o(t[l],u)},X=({onIntersect:e,threshold:n=.1,root:t=null,rootMargin:r="0px",triggerOnce:o=!1,disabled:l=!1,children:s,className:u,style:f})=>{const c=O(null),i=O(null),d=O(!1);return D(()=>{if(l||!c.current)return;if(!window.IntersectionObserver){console.warn("IntersectionObserver is not supported in this browser");return}const m=c.current,p=I=>{I.forEach(S=>{if(S.isIntersecting){if(o&&d.current)return;e(S,i.current),o&&(d.current=!0,i.current?.unobserve(m))}})};return i.current=new IntersectionObserver(p,{root:t,rootMargin:r,threshold:n}),i.current.observe(m),()=>{i.current&&i.current.disconnect()}},[e,n,t,r,o,l]),D(()=>{o||(d.current=!1)},[o]),a.createElement("div",{ref:c,className:u,style:f},s)};function ee(e){const{items:n,renderItem:t,filter:r}=e;return n?a.createElement(E,null,n.map((o,l)=>r&&!r(o)?null:t(o,l))):(console.error("ArrayRender: items is null"),null)}function te({source:e,format:n,children:t}){const r=g(()=>{if(e instanceof Date)return e;if(typeof e=="string"||typeof e=="number"){const l=new Date(e);return isNaN(l.getTime())?null:l}return null},[e]),o=g(()=>r?n?n(r):r.toLocaleString():null,[r,n]);return!o||!t?null:a.createElement(a.Fragment,null,t(o))}const ne="onChange",re="value";function le(e){const{defaultValue:n,onBeforeChange:t,trigger:r=ne,valuePropName:o=re,props:l}=e,s=Object.prototype.hasOwnProperty.call(l,o),[u,f]=A(n),c=s?l[o]:u,i=g(()=>l[r],[l,r]),d=V(m=>{const p=typeof m=="function"?m(c):m;t&&t(p,c)===!1||(s||f(p),i&&i(p))},[s,t,c,i]);return[c,d]}function oe(e,...n){try{const t=e(...n);return t instanceof Promise?t:Promise.resolve(t)}catch(t){return Promise.reject(t)}}const Y=typeof Promise.try=="function"?Promise.try.bind(Promise):oe;function k(e,n={}){let t=typeof e=="function"?e():e;const r=[],{sideEffect:o,transform:l}=n,s=()=>{const c=t;return l?.get?l.get(c):c},u=c=>{const i=t,d=l?.get?l.get(i):i;t=l?.set?l.set(typeof c=="function"?c(d):c):typeof c=="function"?c(d):c,r.forEach(m=>m(t)),o&&Y(o,t,i).catch(m=>{console.error("Error in external state side effect, Please do it within side effects:",m)})},f=()=>{const[c,i]=a.useState(t);return a.useEffect(()=>(r.push(i),()=>{const d=r.indexOf(i);d>-1&&r.splice(d,1)}),[]),[l?.get?l.get(c):c,u]};return{get:s,set:u,use:f,useGetter:()=>{const[c]=f();return c},__listeners:r}}function ae(e,n,t){const{storageType:r="local",sideEffect:o,transform:l}=t??{},s=r==="local"?localStorage:sessionStorage;let u=n;const f=s.getItem(e);if(f)try{u=JSON.parse(f)}catch(c){console.warn(`Failed to parse ${r}Storage value for key "${e}", using initial state:`,c),u=n}return k(u,{sideEffect:c=>{s.setItem(e,JSON.stringify(c)),o?.(c)},transform:l})}function se(e,n){const t=n||new Date,r=t.getFullYear(),o=t.getMonth()+1,l=t.getDate(),s=t.getHours(),u=t.getMinutes(),f=t.getSeconds(),c=t.getMilliseconds(),i=t.getDay(),d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],m=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],p=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],I=["January","February","March","April","May","June","July","August","September","October","November","December"],S=m[i],T=d[i],C=o-1,j=I[C],J=p[C],R={YY:r.toString().slice(2),YYYY:r.toString(),M:o.toString(),MM:o.toString().padStart(2,"0"),MMM:J,MMMM:j,D:l.toString(),DD:l.toString().padStart(2,"0"),d:i.toString(),dd:T,ddd:T,dddd:S,H:s.toString(),HH:s.toString().padStart(2,"0"),h:(s%12).toString(),hh:(s%12).toString().padStart(2,"0"),m:u.toString(),mm:u.toString().padStart(2,"0"),s:f.toString(),ss:f.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 e.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,_=>R[_])}class ce{count=0;next(){return this.count++}}export{ee as ArrayRender,ce as Counter,te as DateRender,L as False,h as If,X as Observer,G as Pipe,q as Scope,$ as SizeBox,x as Styles,y as Switch,Q as Toggle,z as True,U as When,P as childrenLoop,k as createExternalState,ae as createStorageState,F as cx,se as formatDate,Y as safePromiseTry,le as useControlled}; |
{ | ||
"name": "@wwog/react", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "A practical React component library providing declarative flow control and common UI utility components to make your React code more concise and readable.", | ||
@@ -23,2 +23,11 @@ "keywords": [ | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "unbuild", | ||
"format": "biome format --write src", | ||
"check": "biome check --write src", | ||
"test:unit": "vitest run --browser.headless", | ||
"test:types": "tsc --noEmit --skipLibCheck", | ||
"all-suites": "pnpm run format && pnpm run check && pnpm run test:types && pnpm run test:unit", | ||
"test:watch": "vitest" | ||
}, | ||
"devDependencies": { | ||
@@ -45,11 +54,3 @@ "@biomejs/biome": "^1.9.4", | ||
}, | ||
"scripts": { | ||
"build": "unbuild", | ||
"format": "biome format --write src", | ||
"check": "biome check --write src", | ||
"test:unit": "vitest run --browser.headless", | ||
"test:types": "tsc --noEmit --skipLibCheck", | ||
"all-suites": "pnpm run format && pnpm run check && pnpm run test:types && pnpm run test:unit", | ||
"test:watch": "vitest" | ||
} | ||
} | ||
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" | ||
} |
@@ -466,2 +466,6 @@ # @wwog/react | ||
### `createStorageState` (v1.3.2+) | ||
> Extends from createExternalState and uses storage to persist state, supports `localStorage` and `sessionStorage` | ||
```tsx | ||
@@ -468,0 +472,0 @@ import { createExternalState } from "@wwog/react"; |
@@ -203,1 +203,36 @@ import React from "react"; | ||
} | ||
export interface StorageStateOptions<T, U> { | ||
sideEffect?: (newState: T) => void; | ||
transform?: Transform<T, U>; | ||
storageType: "local" | "session"; | ||
} | ||
export function createStorageState<T, U = T>( | ||
key: string, | ||
initialState: T, | ||
options?: StorageStateOptions<T, U> | ||
) { | ||
const { storageType = "local", sideEffect, transform } = options ?? {}; | ||
const storage = storageType === "local" ? localStorage : sessionStorage; | ||
let _initState: T = initialState; | ||
const storedValue = storage.getItem(key); | ||
if (storedValue) { | ||
try { | ||
_initState = JSON.parse(storedValue); | ||
} catch (error) { | ||
console.warn( | ||
`Failed to parse ${storageType}Storage value for key "${key}", using initial state:`, | ||
error | ||
); | ||
_initState = initialState; | ||
} | ||
} | ||
return createExternalState(_initState, { | ||
sideEffect: (newState) => { | ||
storage.setItem(key, JSON.stringify(newState)); | ||
sideEffect?.(newState); | ||
}, | ||
transform, | ||
}); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
121051
6.2%1992
9.09%568
0.71%