@wwog/react 1.3.5 → 1.3.8
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 +13 -2
- package/dist/index.d.mts +3 -6
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/algorithm/date/zellersKongruenz.ts +80 -0
- package/src/algorithm/date.ts +5 -0
- package/src/components/Struct/ArrayRender.tsx +31 -1
- package/src/hooks/{useScreen.tsx → useScreen.ts} +1 -22
package/README.md
CHANGED
|
@@ -167,7 +167,7 @@ import { Toggle } from "@wwog/react";
|
|
|
167
167
|
|
|
168
168
|
#### `<ArrayRender>`
|
|
169
169
|
|
|
170
|
-
Efficiently render array data, supports filtering and custom rendering.
|
|
170
|
+
Efficiently render array data, supports filtering, sorting, and custom rendering. Optimized for performance with minimal loops.
|
|
171
171
|
|
|
172
172
|
```tsx
|
|
173
173
|
import { ArrayRender } from "@wwog/react";
|
|
@@ -177,16 +177,27 @@ function UserList({ users }) {
|
|
|
177
177
|
<ArrayRender
|
|
178
178
|
items={users}
|
|
179
179
|
filter={(user) => user.active}
|
|
180
|
+
sort={(a, b) => a.name.localeCompare(b.name)}
|
|
180
181
|
renderItem={(user, index) => (
|
|
181
182
|
<div key={user.id}>
|
|
182
183
|
{index + 1}. {user.name}
|
|
183
184
|
</div>
|
|
184
185
|
)}
|
|
186
|
+
renderEmpty={() => <div>No users found</div>}
|
|
185
187
|
/>
|
|
186
188
|
);
|
|
187
189
|
}
|
|
188
190
|
```
|
|
189
191
|
|
|
192
|
+
- `items`: Array of data to render
|
|
193
|
+
- `renderItem`: Function to render each item, receives (item, index) as parameters
|
|
194
|
+
- `filter`: Optional filter function to filter items
|
|
195
|
+
- `sort`: Optional sort function for array sorting, uses standard comparison function (a, b) => number
|
|
196
|
+
- `renderEmpty`: Optional function to render content when array is empty
|
|
197
|
+
|
|
198
|
+
**Performance Note**: When no sorting is needed, filtering is done during the map loop for optimal performance. When sorting is provided, filtering is applied first, then sorting, to minimize operations.
|
|
199
|
+
```
|
|
200
|
+
|
|
190
201
|
#### `<Clamp>` (v1.2.14+)
|
|
191
202
|
|
|
192
203
|
> Removed in v1.3.0. The compatibility problem is too big, the desktop web page works well, h5 has a problem.
|
|
@@ -458,7 +469,7 @@ You can also use a container wrapper element:
|
|
|
458
469
|
|
|
459
470
|
- Supports passing in custom breakpoints, defaults to the same breakpoint definitions as TailwindCSS
|
|
460
471
|
|
|
461
|
-
This hook is implemented based on listening. If
|
|
472
|
+
This hook is implemented based on listening. If useScreen needs to be used multiple times without changing the passed parameters, it is recommended to wrap Context
|
|
462
473
|
|
|
463
474
|
Development notes: Internally implemented via `mediaQuery`, it does not listen to a specific breakpoint but is optimized to listen only to the previous and next breakpoints of the current breakpoint for better performance.
|
|
464
475
|
|
package/dist/index.d.mts
CHANGED
|
@@ -465,6 +465,8 @@ interface ArrayRenderProps<T> {
|
|
|
465
465
|
items: T[];
|
|
466
466
|
renderItem: (item: T, index: number) => React$1.ReactNode;
|
|
467
467
|
filter?: (item: T) => boolean;
|
|
468
|
+
renderEmpty?: () => React$1.ReactNode;
|
|
469
|
+
sort?: (a: T, b: T) => number;
|
|
468
470
|
}
|
|
469
471
|
declare function ArrayRender<T>(props: ArrayRenderProps<T>): ReactNode;
|
|
470
472
|
|
|
@@ -716,11 +718,6 @@ type Responsive<T> = T | Partial<Record<BreakpointName, T>>;
|
|
|
716
718
|
|
|
717
719
|
declare function getCurrentBreakpoint(breakpointDesc: BreakpointDesc, width: number): BreakpointName;
|
|
718
720
|
declare function useScreen(breakpointDesc?: BreakpointDesc): "base" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
|
|
719
|
-
declare function BreakpointProvider({ children, breakpointDesc, }: {
|
|
720
|
-
children: React$1.ReactNode;
|
|
721
|
-
breakpointDesc?: BreakpointDesc;
|
|
722
|
-
}): React$1.JSX.Element;
|
|
723
|
-
declare function useBreakpoint(): "base" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
|
|
724
721
|
|
|
725
|
-
export { ArrayRender,
|
|
722
|
+
export { ArrayRender, Counter, DateRender, DefBreakpointDesc, False, If, Observer, Pipe, Scope, SizeBox, Styles, Switch, Toggle, True, When, breakpoints, childrenLoop, createExternalState, createStorageState, cx, formatDate, getCurrentBreakpoint, safePromiseTry, useControlled, useScreen };
|
|
726
723
|
export type { ArrayRenderProps, BreakpointDesc, BreakpointName, CreateStateListener, CxInput, DateRenderProps, ElseIfProps, ElseProps, ExternalSideEffect, ExternalState, ExternalStateOptions, ExternalWithKernel, FalseProps, IfProps, ObserverProps, PipeProps, Responsive, ScopeProps, StorageStateOptions, StylesDescriptor, StylesProps, StylesType, SwitchCaseProps, SwitchDefaultProps, SwitchProps, ThenProps, ToggleProps, Transform, TrueProps, UseControlledOptions, WhenProps };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import a,{useMemo as g,Fragment as E,Children as V,isValidElement as Z,cloneElement as z,useEffect as w,useState as k,useRef as C,useCallback as U,createContext as G,useContext as q}from"react";function Y(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 K=(e,n)=>e===n,v=e=>a.createElement(a.Fragment,null,e.children);v.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=K,children:r,strict:l=!1}=e,o=new Set;let i=null,m=null,d=!1;return Y(r,(s,c)=>{if(!a.isValidElement(s))throw new Error(`Switch Children only accepts valid React elements at index ${c}`);const u=s.type;if(u.displayName===v.displayName){const f=s.props;if(o.has(f.value))throw new Error(`Switch found duplicate Case value at index ${c}: ${JSON.stringify(f.value)}${l?" (detected in strict mode)":""}`);if(o.add(f.value),!i&&t(n,f.value)&&(i=f.children,l===!1))return!1}else if(u.displayName===N.displayName){if(d)throw new Error(`Switch can only have one Default child at index ${c}`);if(d=!0,m=s.props.children,!l&&i)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(u.displayName||u.name||u)} at index ${c}`)}),a.createElement(a.Fragment,null,i??m)};y.displayName="Switch",y.Case=v,y.Default=N,y.createTyped=function(){return{Switch:y,Case:v,Default:N}};const b=e=>a.createElement(a.Fragment,null,e.children),x=({children:e})=>a.createElement(a.Fragment,null,e),M=e=>a.createElement(a.Fragment,null,e.children);b.displayName="If_Then",x.displayName="If_Else",M.displayName="If_ElseIf";const p=({condition:e,children:n})=>{let t=null,r=null;const l=[];if(a.Children.forEach(n,o=>{if(!a.isValidElement(o))throw new Error("If component only accepts valid React elements");const i=o.type;if(i.displayName===b.displayName){if(t)throw new Error("If component can only have one Then child");t=o}else if(i.displayName===M.displayName)l.push(o);else if(i.displayName===x.displayName){if(r)throw new Error("If component can only have one Else child");r=o}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?a.createElement(a.Fragment,null,t.props.children):null;for(const o of l)if(o.props.condition)return a.createElement(a.Fragment,null,o.props.children);return r?a.createElement(a.Fragment,null,r.props.children):null};p.displayName="If",p.Then=b,p.ElseIf=M,p.Else=x,p.createTyped=function(){return{If:p,Then:b,ElseIf:M,Else:x}};const Q=({condition:e,children:n})=>e?a.createElement(a.Fragment,null,n):null,X=({condition:e,children:n})=>e===!1?a.createElement(a.Fragment,null,n):null,ee=({all:e,any:n,none:t,children:r,fallback:l})=>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(o=>!o))),[e,n,t])?a.createElement(a.Fragment,null,r):a.createElement(a.Fragment,null,l||null),te=({data:e,transform:n,render:t,fallback:r})=>{const l=g(()=>n.reduce((o,i)=>i(o),e),[e,n]);return l==null?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,t(l))},ne=e=>{const{children:n,h:t,w:r,size:l,height:o,width:i,className:m}=e;return a.createElement("div",{style:{width:l||r||i,height:l||t||o,flexShrink:0},className:m},n)},re=({let:e,props:n,children:t,fallback:r})=>{const l=g(()=>typeof e=="function"?e(n):e,[e,n]);return!t||!Object.keys(l).length?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,t(l))};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,l]of Object.entries(t))l&&n.add(r)}return Array.from(n).join(" ")}const oe=e=>typeof e=="object"&&!!e,O=({className:e,children:n,asWrapper:t=!1})=>{if(!n)return null;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(V.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),a.createElement(E,null,n);if(Z(n)){const l=n;let o=l?.props?.className;return l?.type?.displayName===O.displayName&&oe(o)&&(o=F(...Object.values(o))),z(n,{className:F(r,o)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),a.createElement(E,null,n)};O.displayName="W/Styles";const le=e=>{const{index:n=0,options:t,next:r,render:l}=e;w(()=>{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[o,i]=k(n),m=()=>{i(d=>t.length?r?r(d,t):(d+1)%t.length:d)};return l(t[o],m)},ae=({onIntersect:e,threshold:n=.1,root:t=null,rootMargin:r="0px",triggerOnce:l=!1,disabled:o=!1,children:i,className:m,style:d})=>{const s=C(null),c=C(null),u=C(!1);return w(()=>{if(o||!s.current)return;if(!window.IntersectionObserver){console.warn("IntersectionObserver is not supported in this browser");return}const f=s.current,h=D=>{D.forEach(I=>{l&&u.current||(e(I,c.current),l&&(u.current=!0,c.current?.unobserve(f)))})};return c.current=new IntersectionObserver(h,{root:t,rootMargin:r,threshold:n}),c.current.observe(f),()=>{c.current&&c.current.disconnect()}},[e,n,t,r,l,o]),w(()=>{l||(u.current=!1)},[l]),a.createElement("div",{ref:s,className:m,style:d},i)};function se(e){const{items:n,renderItem:t,filter:r}=e;return n?a.createElement(E,null,n.map((l,o)=>r&&!r(l)?null:t(l,o))):(console.error("ArrayRender: items is null"),null)}function ie({source:e,format:n,children:t}){const r=g(()=>{if(e instanceof Date)return e;if(typeof e=="string"||typeof e=="number"){const o=new Date(e);return isNaN(o.getTime())?null:o}return null},[e]),l=g(()=>r?n?n(r):r.toLocaleString():null,[r,n]);return!l||!t?null:a.createElement(a.Fragment,null,t(l))}const ce="onChange",ue="value";function de(e){const{defaultValue:n,onBeforeChange:t,trigger:r=ce,valuePropName:l=ue,props:o}=e,i=Object.prototype.hasOwnProperty.call(o,l),[m,d]=k(n),s=i?o[l]:m,c=g(()=>o[r],[o,r]),u=U(f=>{const h=typeof f=="function"?f(s):f;t&&t(h,s)===!1||(i||d(h),c&&c(h))},[i,t,s,c]);return[s,u]}function fe(e,...n){try{const t=e(...n);return t instanceof Promise?t:Promise.resolve(t)}catch(t){return Promise.reject(t)}}const j=typeof Promise.try=="function"?Promise.try.bind(Promise):fe;function J(e,n={}){let t=typeof e=="function"?e():e;const r=[],{sideEffect:l,transform:o}=n,i=()=>{const s=t;return o?.get?o.get(s):s},m=s=>{const c=t,u=o?.get?o.get(c):c;t=o?.set?o.set(typeof s=="function"?s(u):s):typeof s=="function"?s(u):s,r.forEach(f=>f(t)),l&&j(l,t,c).catch(f=>{console.error("Error in external state side effect, Please do it within side effects:",f)})},d=()=>{const[s,c]=a.useState(t);return a.useEffect(()=>(r.push(c),()=>{const u=r.indexOf(c);u>-1&&r.splice(u,1)}),[]),[o?.get?o.get(s):s,m]};return{get:i,set:m,use:d,useGetter:()=>{const[s]=d();return s},__listeners:r}}function me(e,n,t){const{storageType:r="local",sideEffect:l,transform:o}=t??{},i=r==="local"?localStorage:sessionStorage;let m=n;const d=i.getItem(e);if(d)try{m=JSON.parse(d)}catch(s){console.warn(`Failed to parse ${r}Storage value for key "${e}", using initial state:`,s),m=n}return J(m,{sideEffect:s=>{i.setItem(e,JSON.stringify(s)),l?.(s)},transform:o})}function he(e,n){const t=n||new Date,r=t.getFullYear(),l=t.getMonth()+1,o=t.getDate(),i=t.getHours(),m=t.getMinutes(),d=t.getSeconds(),s=t.getMilliseconds(),c=t.getDay(),u=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],f=["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"],I=f[c],T=u[c],A=l-1,_=D[A],$=h[A],L={YY:r.toString().slice(2),YYYY:r.toString(),M:l.toString(),MM:l.toString().padStart(2,"0"),MMM:$,MMMM:_,D:o.toString(),DD:o.toString().padStart(2,"0"),d:c.toString(),dd:T,ddd:T,dddd:I,H:i.toString(),HH:i.toString().padStart(2,"0"),h:(i%12).toString(),hh:(i%12).toString().padStart(2,"0"),m:m.toString(),mm:m.toString().padStart(2,"0"),s:d.toString(),ss:d.toString().padStart(2,"0"),SSS:s.toString().padStart(3,"0"),Z:"+08:00",ZZ:"+0800",A:i<12?"AM":"PM",a:i<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,H=>L[H])}class pe{count=0;next(){return this.count++}}const S=["base","xs","sm","md","lg","xl","2xl","3xl"],B={xs:475,sm:640,md:768,lg:1024,xl:1280,"2xl":1536,"3xl":1920},ge=[...S].reverse();function P(e,n){for(const t of ge){const r=e[t];if(r!==void 0&&!Number.isNaN(r)&&n>=r)return t}return"base"}function W(e=B){const[n,t]=k(P(e,window.innerWidth));return w(()=>{let r=[],l=[];const o=()=>{l.forEach(c=>c()),r=[],l=[];const i=P(e,window.innerWidth);t(i);const m=S.indexOf(i),d=S[m+1];if(d&&e[d]!==void 0){const c=e[d];if(Number.isNaN(c))throw new Error(`Invalid breakpoint value for ${d}: ${e[d]}`);{const u=window.matchMedia(`(min-width: ${c}px)`);r.push(u);const f=()=>o();u.addEventListener("change",f),l.push(()=>u.removeEventListener("change",f))}}const s=S[m-1];if(s&&e[s]!==void 0){const c=e[s];if(Number.isNaN(c))throw new Error(`Invalid breakpoint value for ${s}: ${e[s]}`);{const u=window.matchMedia(`(max-width: ${c-1}px)`);r.push(u);const f=()=>o();u.addEventListener("change",f),l.push(()=>u.removeEventListener("change",f))}}};return o(),()=>{l.forEach(i=>i())}},[e]),n}const R=G("base");function ye({children:e,breakpointDesc:n}){const t=W(n);return a.createElement(R.Provider,{value:t},e)}function Se(){return q(R)}export{se as ArrayRender,ye as BreakpointProvider,pe as Counter,ie as DateRender,B as DefBreakpointDesc,X as False,p as If,ae as Observer,te as Pipe,re as Scope,ne as SizeBox,O as Styles,y as Switch,le as Toggle,Q as True,ee as When,S as breakpoints,Y as childrenLoop,J as createExternalState,me as createStorageState,F as cx,he as formatDate,P as getCurrentBreakpoint,j as safePromiseTry,Se as useBreakpoint,de as useControlled,W as useScreen};
|
|
1
|
+
import s,{useMemo as g,Fragment as S,Children as L,isValidElement as H,cloneElement as V,useEffect as w,useState as O,useRef as k,useCallback as Z}from"react";function Y(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,v=e=>s.createElement(s.Fragment,null,e.children);v.displayName="Switch_Case";const N=e=>s.createElement(s.Fragment,null,e.children);N.displayName="Switch_Default";const y=e=>{const{value:n,compare:t=z,children:r,strict:l=!1}=e,o=new Set;let a=null,u=null,d=!1;return Y(r,(i,c)=>{if(!s.isValidElement(i))throw new Error(`Switch Children only accepts valid React elements at index ${c}`);const f=i.type;if(f.displayName===v.displayName){const m=i.props;if(o.has(m.value))throw new Error(`Switch found duplicate Case value at index ${c}: ${JSON.stringify(m.value)}${l?" (detected in strict mode)":""}`);if(o.add(m.value),!a&&t(n,m.value)&&(a=m.children,l===!1))return!1}else if(f.displayName===N.displayName){if(d)throw new Error(`Switch can only have one Default child at index ${c}`);if(d=!0,u=i.props.children,!l&&a)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(f.displayName||f.name||f)} at index ${c}`)}),s.createElement(s.Fragment,null,a??u)};y.displayName="Switch",y.Case=v,y.Default=N,y.createTyped=function(){return{Switch:y,Case:v,Default:N}};const b=e=>s.createElement(s.Fragment,null,e.children),M=({children:e})=>s.createElement(s.Fragment,null,e),x=e=>s.createElement(s.Fragment,null,e.children);b.displayName="If_Then",M.displayName="If_Else",x.displayName="If_ElseIf";const p=({condition:e,children:n})=>{let t=null,r=null;const l=[];if(s.Children.forEach(n,o=>{if(!s.isValidElement(o))throw new Error("If component only accepts valid React elements");const a=o.type;if(a.displayName===b.displayName){if(t)throw new Error("If component can only have one Then child");t=o}else if(a.displayName===x.displayName)l.push(o);else if(a.displayName===M.displayName){if(r)throw new Error("If component can only have one Else child");r=o}else throw new Error(`If component only accepts 'Then', 'ElseIf', or 'Else' elements as children, found: ${String(a.displayName||a.name||a)}`)}),e)return t?s.createElement(s.Fragment,null,t.props.children):null;for(const o of l)if(o.props.condition)return s.createElement(s.Fragment,null,o.props.children);return r?s.createElement(s.Fragment,null,r.props.children):null};p.displayName="If",p.Then=b,p.ElseIf=x,p.Else=M,p.createTyped=function(){return{If:p,Then:b,ElseIf:x,Else:M}};const U=({condition:e,children:n})=>e?s.createElement(s.Fragment,null,n):null,G=({condition:e,children:n})=>e===!1?s.createElement(s.Fragment,null,n):null,q=({all:e,any:n,none:t,children:r,fallback:l})=>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(o=>!o))),[e,n,t])?s.createElement(s.Fragment,null,r):s.createElement(s.Fragment,null,l||null),K=({data:e,transform:n,render:t,fallback:r})=>{const l=g(()=>n.reduce((o,a)=>a(o),e),[e,n]);return l==null?s.createElement(s.Fragment,null,r||null):s.createElement(s.Fragment,null,t(l))},Q=e=>{const{children:n,h:t,w:r,size:l,height:o,width:a,className:u}=e;return s.createElement("div",{style:{width:l||r||a,height:l||t||o,flexShrink:0},className:u},n)},X=({let:e,props:n,children:t,fallback:r})=>{const l=g(()=>typeof e=="function"?e(n):e,[e,n]);return!t||!Object.keys(l).length?s.createElement(s.Fragment,null,r||null):s.createElement(s.Fragment,null,t(l))};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,l]of Object.entries(t))l&&n.add(r)}return Array.from(n).join(" ")}const ee=e=>typeof e=="object"&&!!e,C=({className:e,children:n,asWrapper:t=!1})=>{if(!n)return null;if(!e)return s.createElement(S,null,n);const r=typeof e=="string"?e:F(...Object.values(e));if(t)return s.createElement(t===!0?"div":t,{className:r},n);if(L.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),s.createElement(S,null,n);if(H(n)){const l=n;let o=l?.props?.className;return l?.type?.displayName===C.displayName&&ee(o)&&(o=F(...Object.values(o))),V(n,{className:F(r,o)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),s.createElement(S,null,n)};C.displayName="W/Styles";const te=e=>{const{index:n=0,options:t,next:r,render:l}=e;w(()=>{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[o,a]=O(n),u=()=>{a(d=>t.length?r?r(d,t):(d+1)%t.length:d)};return l(t[o],u)},ne=({onIntersect:e,threshold:n=.1,root:t=null,rootMargin:r="0px",triggerOnce:l=!1,disabled:o=!1,children:a,className:u,style:d})=>{const i=k(null),c=k(null),f=k(!1);return w(()=>{if(o||!i.current)return;if(!window.IntersectionObserver){console.warn("IntersectionObserver is not supported in this browser");return}const m=i.current,h=I=>{I.forEach(D=>{l&&f.current||(e(D,c.current),l&&(f.current=!0,c.current?.unobserve(m)))})};return c.current=new IntersectionObserver(h,{root:t,rootMargin:r,threshold:n}),c.current.observe(m),()=>{c.current&&c.current.disconnect()}},[e,n,t,r,l,o]),w(()=>{l||(f.current=!1)},[l]),s.createElement("div",{ref:i,className:u,style:d},a)};function re(e){const{items:n,renderItem:t,filter:r,renderEmpty:l,sort:o}=e;if(!n)return console.error("ArrayRender: items is null"),null;if(n.length===0)return l?l():null;if(o){let a=[...n];return r&&(a=a.filter(r)),a=a.sort(o),a.length===0?l?l():null:s.createElement(S,null,a.map((u,d)=>t(u,d)))}return s.createElement(S,null,n.map((a,u)=>r&&!r(a)?null:t(a,u)))}function le({source:e,format:n,children:t}){const r=g(()=>{if(e instanceof Date)return e;if(typeof e=="string"||typeof e=="number"){const o=new Date(e);return isNaN(o.getTime())?null:o}return null},[e]),l=g(()=>r?n?n(r):r.toLocaleString():null,[r,n]);return!l||!t?null:s.createElement(s.Fragment,null,t(l))}const oe="onChange",ae="value";function se(e){const{defaultValue:n,onBeforeChange:t,trigger:r=oe,valuePropName:l=ae,props:o}=e,a=Object.prototype.hasOwnProperty.call(o,l),[u,d]=O(n),i=a?o[l]:u,c=g(()=>o[r],[o,r]),f=Z(m=>{const h=typeof m=="function"?m(i):m;t&&t(h,i)===!1||(a||d(h),c&&c(h))},[a,t,i,c]);return[i,f]}function ie(e,...n){try{const t=e(...n);return t instanceof Promise?t:Promise.resolve(t)}catch(t){return Promise.reject(t)}}const j=typeof Promise.try=="function"?Promise.try.bind(Promise):ie;function J(e,n={}){let t=typeof e=="function"?e():e;const r=[],{sideEffect:l,transform:o}=n,a=()=>{const i=t;return o?.get?o.get(i):i},u=i=>{const c=t,f=o?.get?o.get(c):c;t=o?.set?o.set(typeof i=="function"?i(f):i):typeof i=="function"?i(f):i,r.forEach(m=>m(t)),l&&j(l,t,c).catch(m=>{console.error("Error in external state side effect, Please do it within side effects:",m)})},d=()=>{const[i,c]=s.useState(t);return s.useEffect(()=>(r.push(c),()=>{const f=r.indexOf(c);f>-1&&r.splice(f,1)}),[]),[o?.get?o.get(i):i,u]};return{get:a,set:u,use:d,useGetter:()=>{const[i]=d();return i},__listeners:r}}function ce(e,n,t){const{storageType:r="local",sideEffect:l,transform:o}=t??{},a=r==="local"?localStorage:sessionStorage;let u=n;const d=a.getItem(e);if(d)try{u=JSON.parse(d)}catch(i){console.warn(`Failed to parse ${r}Storage value for key "${e}", using initial state:`,i),u=n}return J(u,{sideEffect:i=>{a.setItem(e,JSON.stringify(i)),l?.(i)},transform:o})}function ue(e,n){const t=n||new Date,r=t.getFullYear(),l=t.getMonth()+1,o=t.getDate(),a=t.getHours(),u=t.getMinutes(),d=t.getSeconds(),i=t.getMilliseconds(),c=t.getDay(),f=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],m=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],h=["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"],D=m[c],A=f[c],P=l-1,B=I[P],R=h[P],_={YY:r.toString().slice(2),YYYY:r.toString(),M:l.toString(),MM:l.toString().padStart(2,"0"),MMM:R,MMMM:B,D:o.toString(),DD:o.toString().padStart(2,"0"),d:c.toString(),dd:A,ddd:A,dddd:D,H:a.toString(),HH:a.toString().padStart(2,"0"),h:(a%12).toString(),hh:(a%12).toString().padStart(2,"0"),m:u.toString(),mm:u.toString().padStart(2,"0"),s:d.toString(),ss:d.toString().padStart(2,"0"),SSS:i.toString().padStart(3,"0"),Z:"+08:00",ZZ:"+0800",A:a<12?"AM":"PM",a:a<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,$=>_[$])}class de{count=0;next(){return this.count++}}const E=["base","xs","sm","md","lg","xl","2xl","3xl"],W={xs:475,sm:640,md:768,lg:1024,xl:1280,"2xl":1536,"3xl":1920},fe=[...E].reverse();function T(e,n){for(const t of fe){const r=e[t];if(r!==void 0&&!Number.isNaN(r)&&n>=r)return t}return"base"}function me(e=W){const[n,t]=O(T(e,window.innerWidth));return w(()=>{let r=[],l=[];const o=()=>{l.forEach(c=>c()),r=[],l=[];const a=T(e,window.innerWidth);t(a);const u=E.indexOf(a),d=E[u+1];if(d&&e[d]!==void 0){const c=e[d];if(Number.isNaN(c))throw new Error(`Invalid breakpoint value for ${d}: ${e[d]}`);{const f=window.matchMedia(`(min-width: ${c}px)`);r.push(f);const m=()=>o();f.addEventListener("change",m),l.push(()=>f.removeEventListener("change",m))}}const i=E[u-1];if(i&&e[i]!==void 0){const c=e[i];if(Number.isNaN(c))throw new Error(`Invalid breakpoint value for ${i}: ${e[i]}`);{const f=window.matchMedia(`(max-width: ${c-1}px)`);r.push(f);const m=()=>o();f.addEventListener("change",m),l.push(()=>f.removeEventListener("change",m))}}};return o(),()=>{l.forEach(a=>a())}},[e]),n}export{re as ArrayRender,de as Counter,le as DateRender,W as DefBreakpointDesc,G as False,p as If,ne as Observer,K as Pipe,X as Scope,Q as SizeBox,C as Styles,y as Switch,te as Toggle,U as True,q as When,E as breakpoints,Y as childrenLoop,J as createExternalState,ce as createStorageState,F as cx,ue as formatDate,T as getCurrentBreakpoint,j as safePromiseTry,se as useControlled,me as useScreen};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wwog/react",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
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",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
蔡勒公式(德语:Zellers Kongruenz),是一种计算任何一日属一星期中哪一日的算法,由十九世纪德国数学家克里斯提安·蔡勒推算出来。
|
|
3
|
+
|
|
4
|
+
对于公历,蔡勒公式为
|
|
5
|
+
h = (q + [13(m + 1)/5] + K + [K/4] + [J/4] - 2J) mod 7
|
|
6
|
+
对于儒略历,蔡勒公式为
|
|
7
|
+
h = (q + [13(m + 1)/5] + K + [K/4] + 5 - J) mod 7
|
|
8
|
+
|
|
9
|
+
h 表示星期几(0 = 星期六,1 = 星期日,2 = 星期一,...,6 = 星期五)
|
|
10
|
+
q 代表月份中的日期
|
|
11
|
+
m 代表月份(3=三月,4=四月,5=五月,...,14=二月)
|
|
12
|
+
K 代表世纪中的年份 ((adjYear) mod 100)
|
|
13
|
+
J 是从零开始的世纪数(实际上是 ⌊(adjYear)/100⌋)
|
|
14
|
+
[...] 表示取整函数
|
|
15
|
+
注意:在此算法中,一月和二月被视为上一年的第 13 和第 14 个月。
|
|
16
|
+
对于ISO 周期中的星期几 d (1 ..= 7)
|
|
17
|
+
d = ((h + 5) mod 7) + 1
|
|
18
|
+
|
|
19
|
+
上面公式依赖于数学家对模除法的定义,即−2 mod 7 等于正 5。
|
|
20
|
+
遗憾的是,在大多数计算机语言实现取余函数时采用截断方式,−2 mod 7 会返回−2 的结果。
|
|
21
|
+
因此,要在计算机上实现泽勒同余,应略微调整公式以确保分子为正。
|
|
22
|
+
最简单的办法是将−2J 替换为+5J,将−J 替换为+6J。
|
|
23
|
+
|
|
24
|
+
对于公历,蔡勒公式变体为:
|
|
25
|
+
h = (q + [13(m + 1)/5] + K + [K / 4] + [J / 4] + 5J) mod 7
|
|
26
|
+
对于儒略历,蔡勒公式变体为:
|
|
27
|
+
h = (q + [13(m + 1)/5] + K + [K / 4] + 5 + 6J) mod 7
|
|
28
|
+
|
|
29
|
+
在使用计算机时,年份处理为4位数更简单,因此RFC 3339附录B中提及用于公历的情况
|
|
30
|
+
对于公历, 变体为:
|
|
31
|
+
h + (q + [ 13(m +1) /5] + Y + [Y /4] -[Y/100] + [Y/400] ) mod 7
|
|
32
|
+
对于儒略历, 变体为:
|
|
33
|
+
h = (q + [13(m + 1)/5] + Y + [Y / 4] + 5) mod 7
|
|
34
|
+
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 计算给定日期的星期几(基于 Michael Keith & Tom Craver 的优化算法)仅公历
|
|
39
|
+
* @param y - 年份(4位数,如 2023)
|
|
40
|
+
* @param m - 月份(1-12)
|
|
41
|
+
* @param d - 日期(1-31)
|
|
42
|
+
* @returns 星期几(0=周日, 1=周一, ..., 6=周六)
|
|
43
|
+
*/
|
|
44
|
+
export function weekday(y: number, m: number, d: number): number {
|
|
45
|
+
const adjustedY = m < 3 ? y - 1 : y - 2;
|
|
46
|
+
const adjustedD = d + adjustedY;
|
|
47
|
+
return (
|
|
48
|
+
(Math.floor((23 * m) / 9) +
|
|
49
|
+
adjustedD +
|
|
50
|
+
4 +
|
|
51
|
+
Math.floor(y / 4) -
|
|
52
|
+
Math.floor(y / 100) +
|
|
53
|
+
Math.floor(y / 400)) %
|
|
54
|
+
7
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 计算儒略历日期的星期几
|
|
60
|
+
* @param y - 年份(4位数,如 1582)
|
|
61
|
+
* @param m - 月份(1-12)
|
|
62
|
+
* @param d - 日期(1-31)
|
|
63
|
+
* @returns 星期几(0=周六, 1=周日, ..., 6=周五)
|
|
64
|
+
*/
|
|
65
|
+
export function weekdayJulian(y: number, m: number, d: number): number {
|
|
66
|
+
const adjustedY = m < 3 ? y - 1 : y;
|
|
67
|
+
const adjustedD = d + adjustedY;
|
|
68
|
+
if (m < 3) {
|
|
69
|
+
m += 12;
|
|
70
|
+
y--;
|
|
71
|
+
}
|
|
72
|
+
return (
|
|
73
|
+
(adjustedD +
|
|
74
|
+
Math.floor((13 * (m + 1)) / 5) +
|
|
75
|
+
adjustedY +
|
|
76
|
+
Math.floor(adjustedY / 4) +
|
|
77
|
+
5) %
|
|
78
|
+
7
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -5,18 +5,48 @@ export interface ArrayRenderProps<T> {
|
|
|
5
5
|
items: T[];
|
|
6
6
|
renderItem: (item: T, index: number) => React.ReactNode;
|
|
7
7
|
filter?: (item: T) => boolean;
|
|
8
|
+
renderEmpty?: () => React.ReactNode;
|
|
9
|
+
sort?: (a: T, b: T) => number;
|
|
8
10
|
}
|
|
9
11
|
//#endregion component Types
|
|
10
12
|
|
|
11
13
|
//#region component
|
|
12
14
|
export function ArrayRender<T>(props: ArrayRenderProps<T>): ReactNode {
|
|
13
|
-
const { items, renderItem, filter } = props;
|
|
15
|
+
const { items, renderItem, filter, renderEmpty, sort } = props;
|
|
14
16
|
|
|
15
17
|
if (!items) {
|
|
16
18
|
console.error("ArrayRender: items is null");
|
|
17
19
|
return null;
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
if (items.length === 0) {
|
|
23
|
+
return renderEmpty ? renderEmpty() : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 如果需要排序,先处理排序和过滤
|
|
27
|
+
if (sort) {
|
|
28
|
+
let processedItems = [...items];
|
|
29
|
+
|
|
30
|
+
if (filter) {
|
|
31
|
+
processedItems = processedItems.filter(filter);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
processedItems = processedItems.sort(sort);
|
|
35
|
+
|
|
36
|
+
if (processedItems.length === 0) {
|
|
37
|
+
return renderEmpty ? renderEmpty() : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Fragment>
|
|
42
|
+
{processedItems.map((item, index) => {
|
|
43
|
+
return renderItem(item, index);
|
|
44
|
+
})}
|
|
45
|
+
</Fragment>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 如果不需要排序,保持原来的循环中过滤方式
|
|
20
50
|
return (
|
|
21
51
|
<Fragment>
|
|
22
52
|
{items.map((item, index) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
breakpoints,
|
|
4
4
|
DefBreakpointDesc,
|
|
@@ -97,24 +97,3 @@ export function useScreen(breakpointDesc: BreakpointDesc = DefBreakpointDesc) {
|
|
|
97
97
|
|
|
98
98
|
return currentBreakpoint;
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
const BreakpointContext = createContext<BreakpointName>("base");
|
|
102
|
-
|
|
103
|
-
export function BreakpointProvider({
|
|
104
|
-
children,
|
|
105
|
-
breakpointDesc,
|
|
106
|
-
}: {
|
|
107
|
-
children: React.ReactNode;
|
|
108
|
-
breakpointDesc?: BreakpointDesc;
|
|
109
|
-
}) {
|
|
110
|
-
const breakpoint = useScreen(breakpointDesc);
|
|
111
|
-
return (
|
|
112
|
-
<BreakpointContext.Provider value={breakpoint}>
|
|
113
|
-
{children}
|
|
114
|
-
</BreakpointContext.Provider>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function useBreakpoint() {
|
|
119
|
-
return useContext(BreakpointContext);
|
|
120
|
-
}
|