@wwog/react 1.3.4 → 1.3.6
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 +11 -1
- package/dist/index.d.mts +11 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/Layout/Flex.tsx +21 -0
- package/src/components/Layout/index.ts +2 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useScreen.ts +99 -0
- package/src/utils/constants.ts +25 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/sundry.ts +67 -66
package/README.md
CHANGED
|
@@ -191,7 +191,7 @@ function UserList({ users }) {
|
|
|
191
191
|
|
|
192
192
|
> Removed in v1.3.0. The compatibility problem is too big, the desktop web page works well, h5 has a problem.
|
|
193
193
|
|
|
194
|
-
A component for displaying text with a fixed number of lines, ellipsis, and optional extra content.
|
|
194
|
+
A component for displaying text with a fixed number of lines, ellipsis, and optional extra content.
|
|
195
195
|
|
|
196
196
|
```tsx
|
|
197
197
|
import { Clamp } from "@wwog/react";
|
|
@@ -452,6 +452,16 @@ You can also use a container wrapper element:
|
|
|
452
452
|
|
|
453
453
|
- Applied to states that can be controlled or uncontrolled components
|
|
454
454
|
|
|
455
|
+
#### useScreen (v1.3.5+)
|
|
456
|
+
|
|
457
|
+
> Return the current breakpoint name
|
|
458
|
+
|
|
459
|
+
- Supports passing in custom breakpoints, defaults to the same breakpoint definitions as TailwindCSS
|
|
460
|
+
|
|
461
|
+
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
|
+
|
|
463
|
+
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
|
+
|
|
455
465
|
### utils
|
|
456
466
|
|
|
457
467
|
> Internal functions used by some components, which can also be used if needed
|
package/dist/index.d.mts
CHANGED
|
@@ -708,5 +708,14 @@ declare class Counter {
|
|
|
708
708
|
|
|
709
709
|
declare const safePromiseTry: <T, U extends unknown[]>(callbackFn: (...args: U) => T | PromiseLike<T>, ...args: U) => Promise<Awaited<T>>;
|
|
710
710
|
|
|
711
|
-
|
|
712
|
-
|
|
711
|
+
declare const breakpoints: readonly ["base", "xs", "sm", "md", "lg", "xl", "2xl", "3xl"];
|
|
712
|
+
declare const DefBreakpointDesc: BreakpointDesc;
|
|
713
|
+
type BreakpointName = (typeof breakpoints)[number];
|
|
714
|
+
type BreakpointDesc = Partial<Record<BreakpointName, number>>;
|
|
715
|
+
type Responsive<T> = T | Partial<Record<BreakpointName, T>>;
|
|
716
|
+
|
|
717
|
+
declare function getCurrentBreakpoint(breakpointDesc: BreakpointDesc, width: number): BreakpointName;
|
|
718
|
+
declare function useScreen(breakpointDesc?: BreakpointDesc): "base" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
|
|
719
|
+
|
|
720
|
+
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 };
|
|
721
|
+
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 o,{useMemo as y,Fragment as S,Children as W,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,E=e=>o.createElement(o.Fragment,null,e.children);E.displayName="Switch_Case";const w=e=>o.createElement(o.Fragment,null,e.children);w.displayName="Switch_Default";const g=e=>{const{value:n,compare:t=Z,children:r,strict:a=!1}=e,l=new Set;let s=null,u=null,d=!1;return P(r,(c,i)=>{if(!o.isValidElement(c))throw new Error(`Switch Children only accepts valid React elements at index ${i}`);const f=c.type;if(f.displayName===E.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)}${a?" (detected in strict mode)":""}`);if(l.add(m.value),!s&&t(n,m.value)&&(s=m.children,a===!1))return!1}else if(f.displayName===w.displayName){if(d)throw new Error(`Switch can only have one Default child at index ${i}`);if(d=!0,u=c.props.children,!a&&s)return!1}else throw new Error(`Switch Children only accepts 'Case' or 'Default' elements, found: ${String(f.displayName||f.name||f)} at index ${i}`)}),o.createElement(o.Fragment,null,s??u)};g.displayName="Switch",g.Case=E,g.Default=w,g.createTyped=function(){return{Switch:g,Case:E,Default:w}};const N=e=>o.createElement(o.Fragment,null,e.children),v=({children:e})=>o.createElement(o.Fragment,null,e),b=e=>o.createElement(o.Fragment,null,e.children);N.displayName="If_Then",v.displayName="If_Else",b.displayName="If_ElseIf";const h=({condition:e,children:n})=>{let t=null,r=null;const a=[];if(o.Children.forEach(n,l=>{if(!o.isValidElement(l))throw new Error("If component only accepts valid React elements");const s=l.type;if(s.displayName===N.displayName){if(t)throw new Error("If component can only have one Then child");t=l}else if(s.displayName===b.displayName)a.push(l);else if(s.displayName===v.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?o.createElement(o.Fragment,null,t.props.children):null;for(const l of a)if(l.props.condition)return o.createElement(o.Fragment,null,l.props.children);return r?o.createElement(o.Fragment,null,r.props.children):null};h.displayName="If",h.Then=N,h.ElseIf=b,h.Else=v,h.createTyped=function(){return{If:h,Then:N,ElseIf:b,Else:v}};const z=({condition:e,children:n})=>e?o.createElement(o.Fragment,null,n):null,L=({condition:e,children:n})=>e===!1?o.createElement(o.Fragment,null,n):null,U=({all:e,any:n,none:t,children:r,fallback:a})=>y(()=>(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])?o.createElement(o.Fragment,null,r):o.createElement(o.Fragment,null,a||null),G=({data:e,transform:n,render:t,fallback:r})=>{const a=y(()=>n.reduce((l,s)=>s(l),e),[e,n]);return a==null?o.createElement(o.Fragment,null,r||null):o.createElement(o.Fragment,null,t(a))},$=e=>{const{children:n,h:t,w:r,size:a,height:l,width:s,className:u}=e;return o.createElement("div",{style:{width:a||r||s,height:a||t||l,flexShrink:0},className:u},n)},q=({let:e,props:n,children:t,fallback:r})=>{const a=y(()=>typeof e=="function"?e(n):e,[e,n]);return!t||!Object.keys(a).length?o.createElement(o.Fragment,null,r||null):o.createElement(o.Fragment,null,t(a))};function M(...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,a]of Object.entries(t))a&&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(!e)return o.createElement(S,null,n);const r=typeof e=="string"?e:M(...Object.values(e));if(t)return o.createElement(t===!0?"div":t,{className:r},n);if(W.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),o.createElement(S,null,n);if(H(n)){const a=n;let l=a?.props?.className;return a?.type?.displayName===x.displayName&&K(l)&&(l=M(...Object.values(l))),B(n,{className:M(r,l)})}return console.error("<Styles>: children is not a valid React element. Please check your code."),o.createElement(S,null,n)};x.displayName="W/Styles";const Q=e=>{const{index:n=0,options:t,next:r,render:a}=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(d=>t.length?r?r(d,t):(d+1)%t.length:d)};return a(t[l],u)},X=({onIntersect:e,threshold:n=.1,root:t=null,rootMargin:r="0px",triggerOnce:a=!1,disabled:l=!1,children:s,className:u,style:d})=>{const c=O(null),i=O(null),f=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=F=>{F.forEach(I=>{a&&f.current||(e(I,i.current),a&&(f.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,a,l]),D(()=>{a||(f.current=!1)},[a]),o.createElement("div",{ref:c,className:u,style:d},s)};function ee(e){const{items:n,renderItem:t,filter:r}=e;return n?o.createElement(S,null,n.map((a,l)=>r&&!r(a)?null:t(a,l))):(console.error("ArrayRender: items is null"),null)}function te({source:e,format:n,children:t}){const r=y(()=>{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]),a=y(()=>r?n?n(r):r.toLocaleString():null,[r,n]);return!a||!t?null:o.createElement(o.Fragment,null,t(a))}const ne="onChange",re="value";function le(e){const{defaultValue:n,onBeforeChange:t,trigger:r=ne,valuePropName:a=re,props:l}=e,s=Object.prototype.hasOwnProperty.call(l,a),[u,d]=A(n),c=s?l[a]:u,i=y(()=>l[r],[l,r]),f=V(m=>{const p=typeof m=="function"?m(c):m;t&&t(p,c)===!1||(s||d(p),i&&i(p))},[s,t,c,i]);return[c,f]}function ae(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):ae;function k(e,n={}){let t=typeof e=="function"?e():e;const r=[],{sideEffect:a,transform:l}=n,s=()=>{const c=t;return l?.get?l.get(c):c},u=c=>{const i=t,f=l?.get?l.get(i):i;t=l?.set?l.set(typeof c=="function"?c(f):c):typeof c=="function"?c(f):c,r.forEach(m=>m(t)),a&&Y(a,t,i).catch(m=>{console.error("Error in external state side effect, Please do it within side effects:",m)})},d=()=>{const[c,i]=o.useState(t);return o.useEffect(()=>(r.push(i),()=>{const f=r.indexOf(i);f>-1&&r.splice(f,1)}),[]),[l?.get?l.get(c):c,u]};return{get:s,set:u,use:d,useGetter:()=>{const[c]=d();return c},__listeners:r}}function oe(e,n,t){const{storageType:r="local",sideEffect:a,transform:l}=t??{},s=r==="local"?localStorage:sessionStorage;let u=n;const d=s.getItem(e);if(d)try{u=JSON.parse(d)}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)),a?.(c)},transform:l})}function se(e,n){const t=n||new Date,r=t.getFullYear(),a=t.getMonth()+1,l=t.getDate(),s=t.getHours(),u=t.getMinutes(),d=t.getSeconds(),c=t.getMilliseconds(),i=t.getDay(),f=["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"],F=["January","February","March","April","May","June","July","August","September","October","November","December"],I=m[i],T=f[i],C=a-1,j=F[C],J=p[C],R={YY:r.toString().slice(2),YYYY:r.toString(),M:a.toString(),MM:a.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:I,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:d.toString(),ss:d.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,g as Switch,Q as Toggle,z as True,U as When,P as childrenLoop,k as createExternalState,oe as createStorageState,M as cx,se as formatDate,Y as safePromiseTry,le as useControlled};
|
|
1
|
+
import a,{useMemo as g,Fragment as E,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=>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=z,children:r,strict:o=!1}=e,l=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(l.has(f.value))throw new Error(`Switch found duplicate Case value at index ${c}: ${JSON.stringify(f.value)}${o?" (detected in strict mode)":""}`);if(l.add(f.value),!i&&t(n,f.value)&&(i=f.children,o===!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,!o&&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),M=({children:e})=>a.createElement(a.Fragment,null,e),x=e=>a.createElement(a.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 o=[];if(a.Children.forEach(n,l=>{if(!a.isValidElement(l))throw new Error("If component only accepts valid React elements");const i=l.type;if(i.displayName===b.displayName){if(t)throw new Error("If component can only have one Then child");t=l}else if(i.displayName===x.displayName)o.push(l);else if(i.displayName===M.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(i.displayName||i.name||i)}`)}),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};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?a.createElement(a.Fragment,null,n):null,G=({condition:e,children:n})=>e===!1?a.createElement(a.Fragment,null,n):null,q=({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),K=({data:e,transform:n,render:t,fallback:r})=>{const o=g(()=>n.reduce((l,i)=>i(l),e),[e,n]);return o==null?a.createElement(a.Fragment,null,r||null):a.createElement(a.Fragment,null,t(o))},Q=e=>{const{children:n,h:t,w:r,size:o,height:l,width:i,className:m}=e;return a.createElement("div",{style:{width:o||r||i,height:o||t||l,flexShrink:0},className:m},n)},X=({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 ee=e=>typeof e=="object"&&!!e,C=({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(L.count(n)>1)return console.error("<Styles>: children has more than one child. Please check your code."),a.createElement(E,null,n);if(H(n)){const o=n;let l=o?.props?.className;return o?.type?.displayName===C.displayName&&ee(l)&&(l=F(...Object.values(l))),V(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)};C.displayName="W/Styles";const te=e=>{const{index:n=0,options:t,next:r,render:o}=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[l,i]=O(n),m=()=>{i(d=>t.length?r?r(d,t):(d+1)%t.length:d)};return o(t[l],m)},ne=({onIntersect:e,threshold:n=.1,root:t=null,rootMargin:r="0px",triggerOnce:o=!1,disabled:l=!1,children:i,className:m,style:d})=>{const s=k(null),c=k(null),u=k(!1);return w(()=>{if(l||!s.current)return;if(!window.IntersectionObserver){console.warn("IntersectionObserver is not supported in this browser");return}const f=s.current,h=I=>{I.forEach(D=>{o&&u.current||(e(D,c.current),o&&(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,o,l]),w(()=>{o||(u.current=!1)},[o]),a.createElement("div",{ref:s,className:m,style:d},i)};function re(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 le({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 oe="onChange",ae="value";function se(e){const{defaultValue:n,onBeforeChange:t,trigger:r=oe,valuePropName:o=ae,props:l}=e,i=Object.prototype.hasOwnProperty.call(l,o),[m,d]=O(n),s=i?l[o]:m,c=g(()=>l[r],[l,r]),u=Z(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 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:o,transform:l}=n,i=()=>{const s=t;return l?.get?l.get(s):s},m=s=>{const c=t,u=l?.get?l.get(c):c;t=l?.set?l.set(typeof s=="function"?s(u):s):typeof s=="function"?s(u):s,r.forEach(f=>f(t)),o&&j(o,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)}),[]),[l?.get?l.get(s):s,m]};return{get:i,set:m,use:d,useGetter:()=>{const[s]=d();return s},__listeners:r}}function ce(e,n,t){const{storageType:r="local",sideEffect:o,transform:l}=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)),o?.(s)},transform:l})}function ue(e,n){const t=n||new Date,r=t.getFullYear(),o=t.getMonth()+1,l=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"],I=["January","February","March","April","May","June","July","August","September","October","November","December"],D=f[c],A=u[c],P=o-1,B=I[P],R=h[P],_={YY:r.toString().slice(2),YYYY:r.toString(),M:o.toString(),MM:o.toString().padStart(2,"0"),MMM:R,MMMM:B,D:l.toString(),DD:l.toString().padStart(2,"0"),d:c.toString(),dd:A,ddd:A,dddd:D,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,$=>_[$])}class de{count=0;next(){return this.count++}}const S=["base","xs","sm","md","lg","xl","2xl","3xl"],W={xs:475,sm:640,md:768,lg:1024,xl:1280,"2xl":1536,"3xl":1920},fe=[...S].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=[],o=[];const l=()=>{o.forEach(c=>c()),r=[],o=[];const i=T(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=()=>l();u.addEventListener("change",f),o.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=()=>l();u.addEventListener("change",f),o.push(()=>u.removeEventListener("change",f))}}};return l(),()=>{o.forEach(i=>i())}},[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,S 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.6",
|
|
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,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { FC, ReactNode } from "react";
|
|
3
|
+
import type { BreakpointDesc, Responsive } from "../../utils/constants";
|
|
4
|
+
|
|
5
|
+
interface FlexProps {
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
breakpointDesc?: BreakpointDesc;
|
|
8
|
+
type?: Responsive<"row" | "column" | "row-reverse" | "column-reverse">;
|
|
9
|
+
}
|
|
10
|
+
export const Flex: FC<FlexProps> = (props) => {
|
|
11
|
+
const { type } = props;
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
style={{
|
|
15
|
+
display: "flex",
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
{props.children}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
breakpoints,
|
|
4
|
+
DefBreakpointDesc,
|
|
5
|
+
type BreakpointDesc,
|
|
6
|
+
type BreakpointName,
|
|
7
|
+
} from "../utils";
|
|
8
|
+
|
|
9
|
+
const reverseBreakpoints = [...breakpoints].reverse();
|
|
10
|
+
|
|
11
|
+
export function getCurrentBreakpoint(
|
|
12
|
+
breakpointDesc: BreakpointDesc,
|
|
13
|
+
width: number
|
|
14
|
+
): BreakpointName {
|
|
15
|
+
for (const bp of reverseBreakpoints) {
|
|
16
|
+
const bpValue = breakpointDesc[bp];
|
|
17
|
+
if (bpValue !== undefined && !Number.isNaN(bpValue) && width >= bpValue) {
|
|
18
|
+
return bp;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return "base";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useScreen(breakpointDesc: BreakpointDesc = DefBreakpointDesc) {
|
|
25
|
+
const [currentBreakpoint, setCurrentBreakpoint] = useState<BreakpointName>(
|
|
26
|
+
getCurrentBreakpoint(breakpointDesc, window.innerWidth)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
let mediaQueries: MediaQueryList[] = [];
|
|
31
|
+
let listeners: (() => void)[] = [];
|
|
32
|
+
|
|
33
|
+
const updateMediaQueries = () => {
|
|
34
|
+
// 清理旧的监听器
|
|
35
|
+
listeners.forEach((removeListener) => removeListener());
|
|
36
|
+
mediaQueries = [];
|
|
37
|
+
listeners = [];
|
|
38
|
+
|
|
39
|
+
// 计算当前断点
|
|
40
|
+
const currentBp = getCurrentBreakpoint(breakpointDesc, window.innerWidth);
|
|
41
|
+
setCurrentBreakpoint(currentBp);
|
|
42
|
+
|
|
43
|
+
// 找到当前断点的索引
|
|
44
|
+
const currentIndex = breakpoints.indexOf(currentBp);
|
|
45
|
+
|
|
46
|
+
// 监听下一个断点(min-width)
|
|
47
|
+
const nextBp = breakpoints[currentIndex + 1];
|
|
48
|
+
if (nextBp && breakpointDesc[nextBp] !== undefined) {
|
|
49
|
+
const nextMinWidth = breakpointDesc[nextBp];
|
|
50
|
+
if (!Number.isNaN(nextMinWidth)) {
|
|
51
|
+
const mediaQuery = window.matchMedia(
|
|
52
|
+
`(min-width: ${nextMinWidth}px)`
|
|
53
|
+
);
|
|
54
|
+
mediaQueries.push(mediaQuery);
|
|
55
|
+
const handleMediaChange = () => updateMediaQueries();
|
|
56
|
+
mediaQuery.addEventListener("change", handleMediaChange);
|
|
57
|
+
listeners.push(() =>
|
|
58
|
+
mediaQuery.removeEventListener("change", handleMediaChange)
|
|
59
|
+
);
|
|
60
|
+
} else {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Invalid breakpoint value for ${nextBp}: ${breakpointDesc[nextBp]}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 监听上一个断点(max-width)
|
|
68
|
+
const prevBp = breakpoints[currentIndex - 1];
|
|
69
|
+
if (prevBp && breakpointDesc[prevBp] !== undefined) {
|
|
70
|
+
const prevMinWidth = breakpointDesc[prevBp];
|
|
71
|
+
if (!Number.isNaN(prevMinWidth)) {
|
|
72
|
+
const mediaQuery = window.matchMedia(
|
|
73
|
+
`(max-width: ${prevMinWidth - 1}px)`
|
|
74
|
+
);
|
|
75
|
+
mediaQueries.push(mediaQuery);
|
|
76
|
+
const handleMediaChange = () => updateMediaQueries();
|
|
77
|
+
mediaQuery.addEventListener("change", handleMediaChange);
|
|
78
|
+
listeners.push(() =>
|
|
79
|
+
mediaQuery.removeEventListener("change", handleMediaChange)
|
|
80
|
+
);
|
|
81
|
+
} else {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Invalid breakpoint value for ${prevBp}: ${breakpointDesc[prevBp]}`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// 初次执行
|
|
90
|
+
updateMediaQueries();
|
|
91
|
+
|
|
92
|
+
// 清理函数
|
|
93
|
+
return () => {
|
|
94
|
+
listeners.forEach((removeListener) => removeListener());
|
|
95
|
+
};
|
|
96
|
+
}, [breakpointDesc]);
|
|
97
|
+
|
|
98
|
+
return currentBreakpoint;
|
|
99
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const breakpoints = [
|
|
2
|
+
"base",
|
|
3
|
+
"xs",
|
|
4
|
+
"sm",
|
|
5
|
+
"md",
|
|
6
|
+
"lg",
|
|
7
|
+
"xl",
|
|
8
|
+
"2xl",
|
|
9
|
+
"3xl",
|
|
10
|
+
] as const;
|
|
11
|
+
|
|
12
|
+
export const DefBreakpointDesc: BreakpointDesc = {
|
|
13
|
+
xs: 475,
|
|
14
|
+
sm: 640,
|
|
15
|
+
md: 768,
|
|
16
|
+
lg: 1024,
|
|
17
|
+
xl: 1280,
|
|
18
|
+
"2xl": 1536,
|
|
19
|
+
"3xl": 1920,
|
|
20
|
+
};
|
|
21
|
+
export type BreakpointName = (typeof breakpoints)[number];
|
|
22
|
+
|
|
23
|
+
export type BreakpointDesc = Partial<Record<BreakpointName, number>>;
|
|
24
|
+
|
|
25
|
+
export type Responsive<T> = T | Partial<Record<BreakpointName, T>>;
|
package/src/utils/index.ts
CHANGED
package/src/utils/sundry.ts
CHANGED
|
@@ -28,103 +28,104 @@
|
|
|
28
28
|
* a | am | pm
|
|
29
29
|
*/
|
|
30
30
|
export function formatDate(schema: string, date?: Date): string {
|
|
31
|
-
const d = date || new Date()
|
|
32
|
-
const year = d.getFullYear()
|
|
33
|
-
const month = d.getMonth() + 1
|
|
34
|
-
const day = d.getDate()
|
|
35
|
-
const hour = d.getHours()
|
|
36
|
-
const minute = d.getMinutes()
|
|
37
|
-
const second = d.getSeconds()
|
|
38
|
-
const millisecond = d.getMilliseconds()
|
|
39
|
-
const week = d.getDay()
|
|
40
|
-
const weekName = [
|
|
31
|
+
const d = date || new Date();
|
|
32
|
+
const year = d.getFullYear();
|
|
33
|
+
const month = d.getMonth() + 1;
|
|
34
|
+
const day = d.getDate();
|
|
35
|
+
const hour = d.getHours();
|
|
36
|
+
const minute = d.getMinutes();
|
|
37
|
+
const second = d.getSeconds();
|
|
38
|
+
const millisecond = d.getMilliseconds();
|
|
39
|
+
const week = d.getDay();
|
|
40
|
+
const weekName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
41
41
|
const weekFullName = [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
]
|
|
42
|
+
"Sunday",
|
|
43
|
+
"Monday",
|
|
44
|
+
"Tuesday",
|
|
45
|
+
"Wednesday",
|
|
46
|
+
"Thursday",
|
|
47
|
+
"Friday",
|
|
48
|
+
"Saturday",
|
|
49
|
+
];
|
|
50
50
|
const monthName = [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
]
|
|
51
|
+
"Jan",
|
|
52
|
+
"Feb",
|
|
53
|
+
"Mar",
|
|
54
|
+
"Apr",
|
|
55
|
+
"May",
|
|
56
|
+
"Jun",
|
|
57
|
+
"Jul",
|
|
58
|
+
"Aug",
|
|
59
|
+
"Sep",
|
|
60
|
+
"Oct",
|
|
61
|
+
"Nov",
|
|
62
|
+
"Dec",
|
|
63
|
+
];
|
|
64
64
|
const monthFullName = [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
]
|
|
65
|
+
"January",
|
|
66
|
+
"February",
|
|
67
|
+
"March",
|
|
68
|
+
"April",
|
|
69
|
+
"May",
|
|
70
|
+
"June",
|
|
71
|
+
"July",
|
|
72
|
+
"August",
|
|
73
|
+
"September",
|
|
74
|
+
"October",
|
|
75
|
+
"November",
|
|
76
|
+
"December",
|
|
77
|
+
];
|
|
78
78
|
// 直接使用 week 索引,不进行转换,因为 getDay() 已经返回了正确的星期索引 (0-6)
|
|
79
|
-
const weekFull = weekFullName[week]
|
|
80
|
-
const weekShort = weekName[week]
|
|
81
|
-
const monthIndex = month - 1
|
|
82
|
-
const monthFull = monthFullName[monthIndex]
|
|
83
|
-
const monthShort = monthName[monthIndex]
|
|
79
|
+
const weekFull = weekFullName[week]!;
|
|
80
|
+
const weekShort = weekName[week]!;
|
|
81
|
+
const monthIndex = month - 1;
|
|
82
|
+
const monthFull = monthFullName[monthIndex]!;
|
|
83
|
+
const monthShort = monthName[monthIndex]!;
|
|
84
84
|
const map: Record<string, string> = {
|
|
85
85
|
YY: year.toString().slice(2),
|
|
86
86
|
YYYY: year.toString(),
|
|
87
87
|
M: month.toString(),
|
|
88
|
-
MM: month.toString().padStart(2,
|
|
88
|
+
MM: month.toString().padStart(2, "0"),
|
|
89
89
|
MMM: monthShort,
|
|
90
90
|
MMMM: monthFull,
|
|
91
91
|
D: day.toString(),
|
|
92
|
-
DD: day.toString().padStart(2,
|
|
92
|
+
DD: day.toString().padStart(2, "0"),
|
|
93
93
|
d: week.toString(),
|
|
94
94
|
dd: weekShort,
|
|
95
95
|
ddd: weekShort,
|
|
96
96
|
dddd: weekFull,
|
|
97
97
|
H: hour.toString(),
|
|
98
|
-
HH: hour.toString().padStart(2,
|
|
98
|
+
HH: hour.toString().padStart(2, "0"),
|
|
99
99
|
h: (hour % 12).toString(),
|
|
100
|
-
hh: (hour % 12).toString().padStart(2,
|
|
100
|
+
hh: (hour % 12).toString().padStart(2, "0"),
|
|
101
101
|
m: minute.toString(),
|
|
102
|
-
mm: minute.toString().padStart(2,
|
|
102
|
+
mm: minute.toString().padStart(2, "0"),
|
|
103
103
|
s: second.toString(),
|
|
104
|
-
ss: second.toString().padStart(2,
|
|
105
|
-
SSS: millisecond.toString().padStart(3,
|
|
106
|
-
Z:
|
|
107
|
-
ZZ:
|
|
108
|
-
A: hour < 12 ?
|
|
109
|
-
a: hour < 12 ?
|
|
110
|
-
}
|
|
104
|
+
ss: second.toString().padStart(2, "0"),
|
|
105
|
+
SSS: millisecond.toString().padStart(3, "0"),
|
|
106
|
+
Z: "+08:00",
|
|
107
|
+
ZZ: "+0800",
|
|
108
|
+
A: hour < 12 ? "AM" : "PM",
|
|
109
|
+
a: hour < 12 ? "am" : "pm",
|
|
110
|
+
};
|
|
111
111
|
|
|
112
112
|
return schema.replace(
|
|
113
113
|
/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,
|
|
114
114
|
(match) => {
|
|
115
|
-
return map[match]
|
|
116
|
-
}
|
|
117
|
-
)
|
|
115
|
+
return map[match]!;
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
export class Counter {
|
|
121
|
-
count = 0
|
|
121
|
+
count = 0;
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
124
|
* @description 获取下一个计数值,不考虑越界。
|
|
125
125
|
* @description_en Get the next count value, without considering overflow.
|
|
126
126
|
*/
|
|
127
127
|
next() {
|
|
128
|
-
return this.count
|
|
128
|
+
return this.count++;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
+
|