@koine/react 2.0.0-beta.73 → 2.0.0-beta.75

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.
Files changed (63) hide show
  1. package/FaviconTags.d.ts +9 -0
  2. package/FaviconTags.js +5 -0
  3. package/Meta.d.ts +5 -0
  4. package/Meta.js +5 -0
  5. package/NoJs.d.ts +3 -0
  6. package/NoJs.js +7 -0
  7. package/Polymorphic.d.ts +26 -0
  8. package/Polymorphic.js +1 -0
  9. package/classed.d.ts +8 -0
  10. package/classed.js +41 -0
  11. package/createUseMediaQueryWidth.d.ts +6 -0
  12. package/createUseMediaQueryWidth.js +38 -0
  13. package/extendComponent.d.ts +16 -0
  14. package/extendComponent.js +9 -0
  15. package/index.cjs.js +33 -23
  16. package/index.d.ts +28 -3
  17. package/index.esm.js +33 -26
  18. package/index.js +26 -3
  19. package/mergeRefs.d.ts +2 -0
  20. package/mergeRefs.js +13 -0
  21. package/package.json +245 -5
  22. package/useAsyncFn.d.ts +24 -0
  23. package/useAsyncFn.js +26 -0
  24. package/useFirstMountState.d.ts +2 -0
  25. package/useFirstMountState.js +10 -0
  26. package/useFixedOffset.d.ts +2 -0
  27. package/useFixedOffset.js +42 -0
  28. package/useFocus.d.ts +2 -0
  29. package/useFocus.js +9 -0
  30. package/useInterval.d.ts +2 -0
  31. package/useInterval.js +20 -0
  32. package/useIsomorphicLayoutEffect.d.ts +3 -0
  33. package/useIsomorphicLayoutEffect.js +4 -0
  34. package/useKeyUp.d.ts +2 -0
  35. package/useKeyUp.js +16 -0
  36. package/useMeasure.d.ts +22 -0
  37. package/useMeasure.js +119 -0
  38. package/useMountedState.d.ts +2 -0
  39. package/useMountedState.js +13 -0
  40. package/useNavigateAway.d.ts +3 -0
  41. package/useNavigateAway.js +25 -0
  42. package/usePrevious.d.ts +2 -0
  43. package/usePrevious.js +9 -0
  44. package/usePreviousRef.d.ts +2 -0
  45. package/usePreviousRef.js +9 -0
  46. package/useReveal.d.ts +13 -0
  47. package/useReveal.js +42 -0
  48. package/useScrollPosition.d.ts +7 -0
  49. package/useScrollPosition.js +58 -0
  50. package/useScrollThreshold.d.ts +2 -0
  51. package/useScrollThreshold.js +26 -0
  52. package/useScrollTo.d.ts +2 -0
  53. package/useScrollTo.js +18 -0
  54. package/useSmoothScroll.d.ts +2 -0
  55. package/useSmoothScroll.js +32 -0
  56. package/useSpinDelay.d.ts +2 -0
  57. package/useSpinDelay.js +36 -0
  58. package/useTraceUpdate.d.ts +2 -0
  59. package/useTraceUpdate.js +17 -0
  60. package/useUpdateEffect.d.ts +3 -0
  61. package/useUpdateEffect.js +11 -0
  62. package/useWindowSize.d.ts +3 -0
  63. package/useWindowSize.js +20 -0
@@ -0,0 +1,9 @@
1
+ export type FaviconTagsProps = {
2
+ name: string;
3
+ color?: string;
4
+ safariTabColor?: string;
5
+ tileColor?: string;
6
+ themeColor?: string;
7
+ };
8
+ export declare let FaviconTags: ({ name, color, safariTabColor, tileColor, themeColor, }: FaviconTagsProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default FaviconTags;
package/FaviconTags.js ADDED
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export let FaviconTags = ({ name, color, safariTabColor, tileColor, themeColor, }) => {
3
+ return (_jsxs(_Fragment, { children: [_jsx("link", { rel: "shortcut icon", href: "/favicon.ico", type: "image/x-icon" }), _jsx("link", { rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png" }), _jsx("link", { rel: "icon", type: "image/png", sizes: "32x32", href: "/favicon-32x32.png" }), _jsx("link", { rel: "icon", type: "image/png", sizes: "16x16", href: "/favicon-16x16.png" }), _jsx("link", { rel: "manifest", href: "/site.webmanifest" }), _jsx("link", { rel: "mask-icon", href: "/safari-pinned-tab.svg", color: safariTabColor || color }), _jsx("meta", { name: "apple-mobile-web-app-title", content: name }), _jsx("meta", { name: "application-name", content: name }), _jsx("meta", { name: "msapplication-TileColor", content: tileColor || color }), _jsx("meta", { name: "theme-color", content: themeColor || color })] }));
4
+ };
5
+ export default FaviconTags;
package/Meta.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export type MetaProps = {
2
+ zoom?: boolean;
3
+ };
4
+ export declare let Meta: ({ zoom }: MetaProps) => import("react/jsx-runtime").JSX.Element;
5
+ export default Meta;
package/Meta.js ADDED
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export let Meta = ({ zoom }) => {
3
+ return (_jsx("meta", { name: "viewport", content: `width=device-width, initial-scale=1, maximum-scale=1${zoom ? "" : ", user-scalable=0"}` }));
4
+ };
5
+ export default Meta;
package/NoJs.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export type NoJsProps = Record<string, never>;
2
+ export declare let NoJs: (_props: NoJsProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default NoJs;
package/NoJs.js ADDED
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export let NoJs = (_props) => {
3
+ return (_jsx("script", { id: "no-js", dangerouslySetInnerHTML: {
4
+ __html: `document.querySelector("html").className=document.querySelector("html").className.replace(/no-js/,"") + "js";`,
5
+ } }));
6
+ };
7
+ export default NoJs;
@@ -0,0 +1,26 @@
1
+ export declare namespace Polymorphic {
2
+ type Merge<P1 = Record<string, never>, P2 = Record<string, never>> = Omit<P1, keyof P2> & P2;
3
+ type ComponentTypes = React.ComponentClass<any> | React.FunctionComponent<any> | keyof JSX.IntrinsicElements;
4
+ type InferProps<TComponent extends ComponentTypes> = TComponent extends React.ComponentClass<infer Props> ? Props : TComponent extends React.FunctionComponent<infer Props> ? Props : TComponent extends React.ForwardRefExoticComponent<infer Props> ? Props : TComponent extends keyof JSX.IntrinsicElements ? React.ComponentPropsWithoutRef<TComponent> : never;
5
+ type AsProp<TComponent extends React.ElementType> = {
6
+ as?: TComponent;
7
+ };
8
+ export type Ref<TComponent extends React.ElementType> = React.ComponentPropsWithRef<TComponent>["ref"];
9
+ export type Props<TComponent extends React.ElementType, Props = Record<string, never>> = Omit<InferProps<TComponent>, keyof Props> & AsProp<TComponent> & Props;
10
+ export type PropsWithRef<TComponent extends React.ElementType, TProps = Record<string, never>> = Props<TComponent, TProps> & {
11
+ ref?: Ref<TComponent>;
12
+ };
13
+ type ForwardRefExoticComponent<TComponent, OwnProps> = React.ForwardRefExoticComponent<Merge<TComponent extends React.ElementType ? React.ComponentPropsWithRef<TComponent> : never, OwnProps & {
14
+ as?: TComponent;
15
+ }>>;
16
+ export type ComponentForwarded<TComponent, TProps = Record<string, never>> = ForwardRefExoticComponent<TComponent, TProps> & {
17
+ <As = TComponent>(props: As extends "" ? {
18
+ as: keyof JSX.IntrinsicElements;
19
+ } : As extends React.ComponentType<infer P> ? Merge<P, TProps & {
20
+ as: As;
21
+ }> : As extends keyof JSX.IntrinsicElements ? Merge<JSX.IntrinsicElements[As], TProps & {
22
+ as: As;
23
+ }> : never): React.ReactElement | null;
24
+ };
25
+ export {};
26
+ }
package/Polymorphic.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/classed.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ type ClassedAugmentedProps<Props> = Props & {
3
+ className?: string;
4
+ ref?: React.Ref<any>;
5
+ };
6
+ type ClassedFinalProps<Props, Component> = Component extends React.ReactHTML ? React.HTMLProps<Component> & ClassedAugmentedProps<Props> : ClassedAugmentedProps<Props>;
7
+ export declare let classed: <Props, Component extends React.ElementType<any, keyof React.JSX.IntrinsicElements> = any>(component: Component) => (strings: TemplateStringsArray, ...args: ((props: Props) => string)[] | string[]) => React.ForwardRefExoticComponent<React.PropsWithoutRef<ClassedFinalProps<Props, Component>> & React.RefAttributes<Component>>;
8
+ export default classed;
package/classed.js ADDED
@@ -0,0 +1,41 @@
1
+ import React, { createElement, forwardRef } from "react";
2
+ export let classed = (component) => {
3
+ const type = component.type || component;
4
+ return function (strings, ...args) {
5
+ const WrappedComponent = forwardRef(function (props, ref) {
6
+ const argResolved = args
7
+ .map((arg, index) => {
8
+ let result = "";
9
+ if (typeof arg === "function") {
10
+ result = arg(props);
11
+ }
12
+ else if (typeof arg !== "undefined") {
13
+ result = arg.toString();
14
+ }
15
+ return strings[index] + result;
16
+ })
17
+ .join("");
18
+ const isNativeHtmlElement = typeof type === "string";
19
+ const propsToForward = isNativeHtmlElement
20
+ ? {}
21
+ : props;
22
+ if (isNativeHtmlElement) {
23
+ for (const key in props) {
24
+ if (!key.startsWith("$")) {
25
+ propsToForward[key] = props[key];
26
+ }
27
+ }
28
+ }
29
+ let className = argResolved || strings[0];
30
+ className = className.match(/class="([^"]*)/)?.[1] || className;
31
+ className += props?.className ? " " + props?.className : "";
32
+ return createElement(type, {
33
+ ...propsToForward,
34
+ className: className || undefined,
35
+ ref,
36
+ });
37
+ });
38
+ return WrappedComponent;
39
+ };
40
+ };
41
+ export default classed;
@@ -0,0 +1,6 @@
1
+ import { type GetMediaQueryWidthResolversBreakpoints } from "@koine/utils";
2
+ type _MediaQuerWidthDefExplicit<TBreakpoint extends string> = `min-${TBreakpoint}` | `max-${TBreakpoint}` | `up-${TBreakpoint}` | `down-${TBreakpoint}` | `between-${TBreakpoint}_${TBreakpoint}` | `only-${TBreakpoint}`;
3
+ export type MediaQuerWidthDef<TBreakpoint extends string> = `${TBreakpoint}` | _MediaQuerWidthDefExplicit<TBreakpoint>;
4
+ export type MediaQueryWidth<TBreakpoint extends string> = `@${MediaQuerWidthDef<TBreakpoint>}`;
5
+ export declare let createUseMediaQueryWidth: <TBreakpointsConfig extends GetMediaQueryWidthResolversBreakpoints>(customBreakpoints: TBreakpointsConfig) => <TBreakpoints extends Extract<keyof TBreakpointsConfig, string>>(media: `@${TBreakpoints}` | `@min-${TBreakpoints}` | `@max-${TBreakpoints}` | `@up-${TBreakpoints}` | `@down-${TBreakpoints}` | `@between-${TBreakpoints}_${TBreakpoints}` | `@only-${TBreakpoints}`, serverValue?: null | boolean) => boolean | null;
6
+ export default createUseMediaQueryWidth;
@@ -0,0 +1,38 @@
1
+ import { useState } from "react";
2
+ import { getMediaQueryWidthResolvers, isUndefined, } from "@koine/utils";
3
+ import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
4
+ export let createUseMediaQueryWidth = (customBreakpoints) => {
5
+ const queryResolvers = getMediaQueryWidthResolvers(customBreakpoints);
6
+ return function useMediaQueryWidth(media, serverValue) {
7
+ const definition = media.substring(1);
8
+ let [rule, ruleBreakpoint] = definition.split("-");
9
+ if (isUndefined(ruleBreakpoint)) {
10
+ ruleBreakpoint = rule;
11
+ }
12
+ if (isUndefined(rule)) {
13
+ rule = "min";
14
+ }
15
+ const [br1, br2] = ruleBreakpoint.split("_");
16
+ const query = queryResolvers[rule](br1, br2);
17
+ const [matches, setMatches] = useState(isUndefined(serverValue) ? null : serverValue);
18
+ useIsomorphicLayoutEffect(() => {
19
+ const mq = window.matchMedia(query);
20
+ const handleChange = (event) => {
21
+ setMatches(event.matches);
22
+ };
23
+ setMatches(mq.matches);
24
+ if (!mq.addEventListener) {
25
+ mq.addListener(handleChange);
26
+ return () => {
27
+ mq.removeListener(handleChange);
28
+ };
29
+ }
30
+ mq.addEventListener("change", handleChange);
31
+ return () => {
32
+ mq.removeEventListener("change", handleChange);
33
+ };
34
+ }, [query]);
35
+ return matches;
36
+ };
37
+ };
38
+ export default createUseMediaQueryWidth;
@@ -0,0 +1,16 @@
1
+ export type ExtendableComponent<Props = any> = React.ForwardRefExoticComponent<Props> | React.ExoticComponent<Props> | React.FC<Props> | ((props: Props) => JSX.Element);
2
+ export declare let extendComponent: <Component extends ExtendableComponent<any>, DefaultProps extends {}>(component: Component, defaultProps: DefaultProps) => ((props: import("react").ComponentProps<Component>) => import("react").FunctionComponentElement<any>) & DefaultProps & {
3
+ defaultProps: DefaultProps;
4
+ };
5
+ export interface OverridableComponents {
6
+ [key: string]: {
7
+ type: React.ElementType;
8
+ props: any;
9
+ motionable?: boolean;
10
+ };
11
+ }
12
+ export type WithComponents<Props, Components extends OverridableComponents> = Props & {
13
+ [Name in keyof Components]: NonNullable<Components[Name]["type"] extends keyof JSX.IntrinsicElements ? React.ElementType<Components[Name]["motionable"] extends true ? Omit<React.ComponentPropsWithoutRef<Components[Name]["type"]>, HtmlAttributesCollidingWithMotionProps> & Components[Name]["props"] : React.ComponentPropsWithoutRef<Components[Name]["type"]> & Components[Name]["props"]> : Components[Name]["type"]>;
14
+ };
15
+ type HtmlAttributesCollidingWithMotionProps = "style" | "onDrag" | "onDragStart" | "onDragEnd" | "onAnimationStart" | "onAnimationEnd";
16
+ export default extendComponent;
@@ -0,0 +1,9 @@
1
+ import { createElement } from "react";
2
+ export let extendComponent = (component, defaultProps) => {
3
+ const NewComponent = (props) => createElement(component, props);
4
+ return Object.assign(NewComponent, {
5
+ ...defaultProps,
6
+ defaultProps,
7
+ });
8
+ };
9
+ export default extendComponent;
package/index.cjs.js CHANGED
@@ -4,54 +4,64 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
6
  var utils = require('@koine/utils');
7
+ var jsxRuntime = require('react/jsx-runtime');
7
8
  var dom = require('@koine/dom');
8
9
 
9
- let useMountedState=()=>{let u=react.useRef(!1),n=react.useCallback(()=>u.current,[]);return react.useEffect(()=>(u.current=!0,()=>{u.current=!1;}),[]),n};
10
+ let classed=r=>{let s=r.type||r;return function(r,...a){return react.forwardRef(function(e,n){let o=a.map((t,s)=>{let a="";return "function"==typeof t?a=t(e):void 0!==t&&(a=t.toString()),r[s]+a}).join(""),l="string"==typeof s,i=l?{}:e;if(l)for(let t in e)t.startsWith("$")||(i[t]=e[t]);let c=o||r[0];return c=(c.match(/class="([^"]*)/)?.[1]||c)+(e?.className?" "+e?.className:""),react.createElement(s,{...i,className:c||void 0,ref:n})})}};
10
11
 
11
- let useAsyncFn=(o,l=[],u={loading:!1})=>{let a=react.useRef(0),i=useMountedState(),[d,c]=react.useState(u),g=react.useCallback((...r)=>{let t=++a.current;return d.loading||c(r=>({...r,loading:!0})),o(...r).then(r=>(i()&&t===a.current&&c({value:r,loading:!1}),r),r=>(i()&&t===a.current&&c({error:r,loading:!1}),r))},l);return [d,g]};
12
+ let useIsomorphicLayoutEffect=utils.isBrowser?react.useLayoutEffect:react.useEffect;
12
13
 
13
- let useFirstMountState=()=>{let t=react.useRef(!0);return t.current?(t.current=!1,!0):t.current};
14
+ let createUseMediaQueryWidth=n=>{let a=utils.getMediaQueryWidthResolvers(n);return function(t,n){let[o,s]=t.substring(1).split("-");utils.isUndefined(s)&&(s=o),utils.isUndefined(o)&&(o="min");let[d,m]=s.split("_"),u=a[o](d,m),[c,l]=react.useState(utils.isUndefined(n)?null:n);return useIsomorphicLayoutEffect(()=>{let e=window.matchMedia(u),t=e=>{l(e.matches);};return (l(e.matches),e.addEventListener)?(e.addEventListener("change",t),()=>{e.removeEventListener("change",t);}):(e.addListener(t),()=>{e.removeListener(t);})},[u]),c}};
14
15
 
15
- let useIsomorphicLayoutEffect=utils.isBrowser?react.useLayoutEffect:react.useEffect;
16
+ let extendComponent=(t,o)=>Object.assign(o=>react.createElement(t,o),{...o,defaultProps:o});
16
17
 
17
- let n$1=e=>{dom.injectCss("useFixedOffset",`html{scroll-padding-top: ${e}px}`);};let useFixedOffset=i=>{let c=react.useRef(0);return useIsomorphicLayoutEffect(()=>{let e=()=>{let e=dom.calculateFixedOffset();c.current=e,n$1(e);};if(e(),!ResizeObserver)return dom.listenResizeDebounced(0,e);{let e=new ResizeObserver(e=>{let r=0;e.forEach(e=>{r+=e.contentRect.height;}),c.current=r,utils.debounce(()=>n$1(r),400,!0)();});return dom.$each(i||"[data-fixed]",t=>{e&&e.observe(t);}),()=>{e?.disconnect();}}},[i]),c};
18
+ let FaviconTags=({name:a,color:t,safariTabColor:o,tileColor:c,themeColor:l})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("link",{rel:"shortcut icon",href:"/favicon.ico",type:"image/x-icon"}),jsxRuntime.jsx("link",{rel:"apple-touch-icon",sizes:"180x180",href:"/apple-touch-icon.png"}),jsxRuntime.jsx("link",{rel:"icon",type:"image/png",sizes:"32x32",href:"/favicon-32x32.png"}),jsxRuntime.jsx("link",{rel:"icon",type:"image/png",sizes:"16x16",href:"/favicon-16x16.png"}),jsxRuntime.jsx("link",{rel:"manifest",href:"/site.webmanifest"}),jsxRuntime.jsx("link",{rel:"mask-icon",href:"/safari-pinned-tab.svg",color:o||t}),jsxRuntime.jsx("meta",{name:"apple-mobile-web-app-title",content:a}),jsxRuntime.jsx("meta",{name:"application-name",content:a}),jsxRuntime.jsx("meta",{name:"msapplication-TileColor",content:c||t}),jsxRuntime.jsx("meta",{name:"theme-color",content:l||t})]});
18
19
 
19
- let useFocus=()=>{let e=react.useRef(null);return [e,()=>{e.current&&e.current.focus();}]};
20
+ let mergeRefs=e=>r=>{e.forEach(e=>{"function"==typeof e?e(r):null!=e&&(e.current=r);});};
20
21
 
21
- let useInterval=(n,l,u=[])=>{let o=react.useRef();react.useEffect(()=>{o.current=n;},[n,...u]),react.useEffect(()=>{if(null!==l){let r=setInterval(function(){o.current&&o.current();},l);return ()=>clearInterval(r)}return utils.noop},[l]);};
22
+ let Meta=({zoom:t})=>jsxRuntime.jsx("meta",{name:"viewport",content:`width=device-width, initial-scale=1, maximum-scale=1${t?"":", user-scalable=0"}`});
22
23
 
23
- let useKeyUp=(o,r=[])=>{react.useEffect(()=>dom.on(window,"keyup",e=>{e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||o(e);}),[o,...r]);};
24
+ let NoJs=t=>jsxRuntime.jsx("script",{id:"no-js",dangerouslySetInnerHTML:{__html:'document.querySelector("html").className=document.querySelector("html").className.replace(/no-js/,"") + "js";'}});
24
25
 
25
- let e;let f=e=>{let t=[];if(!e||e===document.body)return t;let{overflow:r,overflowX:n,overflowY:l}=window.getComputedStyle(e);return [r,n,l].some(e=>"auto"===e||"scroll"===e)&&t.push(e),[...t,...f(e.parentElement)]},h=["x","y","top","bottom","left","right","width","height"],p=(e,t)=>h.every(r=>e[r]===t[r]);let useMeasure=h=>{let{scroll:d=!1}=h||{},[a,b]=react.useState({left:0,top:0,width:0,height:0,bottom:0,right:0,x:0,y:0}),g=react.useRef([null,null,null,a]),v=react.useRef(!1);react.useEffect(()=>(v.current=!0,()=>void(v.current=!1)),[]);let[w,,y]=react.useMemo(()=>{let e=(...e)=>{let[t,,,r]=g.current;if(!t)return;let n=t.getBoundingClientRect();Object.freeze(n),v.current&&!p(r,n)&&(g.current[3]=n,b(n));},t=utils.debounce(e);return [e,t,t]},[b]);function x(){let[,e,t]=g.current;e&&(e.forEach(e=>dom.off(e,"scroll",y)),g.current[1]=null),t&&(t.disconnect(),g.current[2]=null);}function z(){let[t,r]=g.current;t&&!e&&ResizeObserver&&(e=new ResizeObserver(y),g.current[2]=e,e.observe(t),d&&r&&r.forEach(e=>dom.on(e,"scroll",y,{capture:!0,passive:!0})));}return react.useEffect(()=>d?dom.listenScrollDebounced(0,w,100):utils.noop,[d,w]),react.useEffect(()=>dom.listenResizeDebounced(0,w,100),[w]),react.useEffect(()=>{x(),z();},[d]),react.useEffect(()=>(w(),x),[]),[e=>{e&&e!==g.current[0]&&(x(),g.current[0]=e,g.current[1]=f(e),z());},a,w]};
26
+ let useMountedState=()=>{let u=react.useRef(!1),n=react.useCallback(()=>u.current,[]);return react.useEffect(()=>(u.current=!0,()=>{u.current=!1;}),[]),n};
26
27
 
27
- let useNavigateAway=o=>{let n=react.useRef();react.useEffect(()=>{n.current=e=>{let r=o(e);return (r&&e.preventDefault(),"string"==typeof r)?e.returnValue=r:e.defaultPrevented?e.returnValue="":void 0};},[o]),react.useEffect(()=>dom.on(window,"beforeunload",e=>n.current?.(e)),[]);};
28
+ let useAsyncFn=(o,u=[],l={loading:!1})=>{let a=react.useRef(0),d=useMountedState(),[i,c]=react.useState(l),g=react.useCallback((...e)=>{let t=++a.current;return i.loading||c(e=>({...e,loading:!0})),o(...e).then(e=>(d()&&t===a.current&&c({value:e,loading:!1}),e),e=>(d()&&t===a.current&&c({error:e,loading:!1}),e))},u);return [i,g]};
28
29
 
29
- let usePrevious=(r,t)=>{let[o,u]=react.useState([r,t]);return o[1]!==r&&u([o[1],r]),o[0]};
30
+ let useFirstMountState=()=>{let r=react.useRef(!0);return r.current?(r.current=!1,!0):r.current};
30
31
 
31
- let usePreviousRef=t=>{let u=react.useRef();return react.useEffect(()=>{u.current=t;}),u.current};
32
+ let n$1=e=>{dom.injectCss("useFixedOffset",`html{scroll-padding-top: ${e}px}`);};let useFixedOffset=i=>{let l=react.useRef(0);return useIsomorphicLayoutEffect(()=>{let e=()=>{let e=dom.calculateFixedOffset();l.current=e,n$1(e);};if(e(),!ResizeObserver)return dom.listenResizeDebounced(0,e);{let e=new ResizeObserver(e=>{let r=0;e.forEach(e=>{r+=e.contentRect.height;}),l.current=r,utils.debounce(()=>n$1(r),400,!0)();});return dom.$each(i||"[data-fixed]",t=>{e&&e.observe(t);}),()=>{e?.disconnect();}}},[i]),l};
32
33
 
33
- let l={x:0,y:0},n=r=>r?.getBoundingClientRect(),u=(r,e)=>{if(!utils.isBrowser)return l;if(!e)return {x:window.scrollX,y:window.scrollY};let o=n(r?.current||document.body),u=n(e.current);return o?u?{x:(u.x||0)-(o.x||0),y:(u.y||0)-(o.y||0)}:{x:o.left,y:o.top}:l};let useScrollPosition=(l,n=[],i,c,m)=>{let f=react.useRef(u(null,c)),s=null,y=()=>{let r=u(i,c);l(r,f.current),f.current=r,s=null;};useIsomorphicLayoutEffect(()=>{if(!utils.isBrowser)return;let r=dom.listenScroll(()=>{m?null===s&&(s=window.setTimeout(y,m)):y();},c?.current);return ()=>{r(),s&&clearTimeout(s);}},n);};
34
+ let useFocus=()=>{let r=react.useRef(null);return [r,()=>{r.current&&r.current.focus();}]};
34
35
 
35
- let useScrollThreshold=(i,m)=>{let[n,f]=react.useState(!1),u=react.useCallback(()=>{if(i){let r=window.scrollY,o=r<i,e=r>i;f(e),m&&m(o,e);}},[i,m]);return react.useEffect(()=>{if(i){let r=dom.listenScroll(u);return u(),r}return utils.noop},[i,u]),n};
36
+ let useInterval=(n,l,u=[])=>{let o=react.useRef();react.useEffect(()=>{o.current=n;},[n,...u]),react.useEffect(()=>{if(null!==l){let r=setInterval(function(){o.current&&o.current();},l);return ()=>clearInterval(r)}return utils.noop},[l]);};
36
37
 
37
- let useSmoothScroll=i=>{let l=useFixedOffset();return react.useCallback((e,m,f,n,u)=>{let c;let p=!1;if(utils.isNumber(e))c=e;else if(e){let t=document.getElementById(e);t&&(c=dom.getOffsetTopSlim(t)-l.current,p=!0);}utils.isNumber(c)&&dom.scrollTo(c=c+(m||0)+(i||p?0:l.current),f,n,u);},[i,l])};
38
+ let useKeyUp=(o,r=[])=>{react.useEffect(()=>dom.on(window,"keyup",e=>{e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||o(e);}),[o,...r]);};
38
39
 
39
- let useSpinDelay=(u,c=500,i=200)=>{let[n,o]=react.useState(0),m=react.useRef();return react.useEffect(()=>{u&&0===n&&(clearTimeout(m.current),m.current=setTimeout(()=>{if(!u)return o(0);m.current=setTimeout(()=>{o(3);},i),o(2);},c),o(1)),u||2===n||(clearTimeout(m.current),o(0));},[u,n,c,i]),react.useEffect(()=>()=>clearTimeout(m.current),[]),2===n||3===n};
40
+ let e;let m=e=>{let t=[];if(!e||e===document.body)return t;let{overflow:r,overflowX:n,overflowY:u}=window.getComputedStyle(e);return [r,n,u].some(e=>"auto"===e||"scroll"===e)&&t.push(e),[...t,...m(e.parentElement)]},p=["x","y","top","bottom","left","right","width","height"],d=(e,t)=>p.every(r=>e[r]===t[r]);let useMeasure=p=>{let{scroll:h=!1}=p||{},[a,b]=react.useState({left:0,top:0,width:0,height:0,bottom:0,right:0,x:0,y:0}),g=react.useRef([null,null,null,a]),v=react.useRef(!1);react.useEffect(()=>(v.current=!0,()=>void(v.current=!1)),[]);let[w,,y]=react.useMemo(()=>{let e=(...e)=>{let[t,,,r]=g.current;if(!t)return;let n=t.getBoundingClientRect();Object.freeze(n),v.current&&!d(r,n)&&(g.current[3]=n,b(n));},t=utils.debounce(e);return [e,t,t]},[b]);function x(){let[,e,t]=g.current;e&&(e.forEach(e=>dom.off(e,"scroll",y)),g.current[1]=null),t&&(t.disconnect(),g.current[2]=null);}function z(){let[t,r]=g.current;t&&!e&&ResizeObserver&&(e=new ResizeObserver(y),g.current[2]=e,e.observe(t),h&&r&&r.forEach(e=>dom.on(e,"scroll",y,{capture:!0,passive:!0})));}return react.useEffect(()=>h?dom.listenScrollDebounced(0,w,100):utils.noop,[h,w]),react.useEffect(()=>dom.listenResizeDebounced(0,w,100),[w]),react.useEffect(()=>{x(),z();},[h]),react.useEffect(()=>(w(),x),[]),[e=>{e&&e!==g.current[0]&&(x(),g.current[0]=e,g.current[1]=m(e),z());},a,w]};
40
41
 
41
- let useTraceUpdate=t=>{let c=react.useRef(t);react.useEffect(()=>{let e=Object.entries(t).reduce((e,[r,t])=>(c.current[r]!==t&&(e[r]=[c.current[r],t]),e),{});Object.keys(e).length>0&&console.info("[@koine/react:useTraceUpdate] changed props:",e),c.current=t;});};
42
+ let useNavigateAway=a=>{let o=react.useRef();react.useEffect(()=>{o.current=e=>{let t=a(e);return (t&&e.preventDefault(),"string"==typeof t)?e.returnValue=t:e.defaultPrevented?e.returnValue="":void 0};},[a]),react.useEffect(()=>dom.on(window,"beforeunload",e=>o.current?.(e)),[]);};
42
43
 
43
- let useUpdateEffect=(r,o)=>{let f=useFirstMountState();react.useEffect(()=>{if(!f)return r()},o);};
44
+ let usePrevious=(r,t)=>{let[o,u]=react.useState([r,t]);return o[1]!==r&&u([o[1],r]),o[0]};
44
45
 
45
- let useWindowSize=(n,o)=>{let[d,m]=react.useState(0),[w,l]=react.useState(0);return react.useEffect(()=>{let e=()=>{m(window.innerWidth),l(window.innerHeight);},r=n?dom.listenResizeDebounced(0,e,n,o):dom.listenResize(e);return e(),r},[n,o]),[d,w]};
46
+ let usePreviousRef=t=>{let u=react.useRef();return react.useEffect(()=>{u.current=t;}),u.current};
46
47
 
47
- let classed=r=>{let n=r.type||r;return function(r,...o){return react.forwardRef(function(e,s){let a=o.map((t,n)=>{let o="";return "function"==typeof t?o=t(e):void 0!==t&&(o=t.toString()),r[n]+o}).join(""),i="string"==typeof n,l=i?{}:e;if(i)for(let t in e)t.startsWith("$")||(l[t]=e[t]);let c=a||r[0];return c=(c.match(/class="([^"]*)/)?.[1]||c)+(e?.className?" "+e?.className:""),react.createElement(n,{...l,className:c||void 0,ref:s})})}};
48
+ let l={x:0,y:0},n=t=>t?.getBoundingClientRect(),u=(t,e)=>{if(!utils.isBrowser)return l;if(!e)return {x:window.scrollX,y:window.scrollY};let o=n(t?.current||document.body),u=n(e.current);return o?u?{x:(u.x||0)-(o.x||0),y:(u.y||0)-(o.y||0)}:{x:o.left,y:o.top}:l};let useScrollPosition=(l,n=[],i,c,m)=>{let f=react.useRef(u(null,c)),s=null,d=()=>{let t=u(i,c);l(t,f.current),f.current=t,s=null;};useIsomorphicLayoutEffect(()=>{if(!utils.isBrowser)return;let t=dom.listenScroll(()=>{m?null===s&&(s=window.setTimeout(d,m)):d();},c?.current);return ()=>{t(),s&&clearTimeout(s);}},n);};
48
49
 
49
- let createUseMediaQueryWidth=i=>{let o=utils.getMediaQueryWidthResolvers(i);return function(t,i){let[s,a]=t.substring(1).split("-");utils.isUndefined(a)&&(a=s),utils.isUndefined(s)&&(s="min");let[m,d]=a.split("_"),l=o[s](m,d),[c,u]=react.useState(utils.isUndefined(i)?null:i);return useIsomorphicLayoutEffect(()=>{let e=window.matchMedia(l),t=e=>{u(e.matches);};return (u(e.matches),e.addEventListener)?(e.addEventListener("change",t),()=>{e.removeEventListener("change",t);}):(e.addListener(t),()=>{e.removeListener(t);})},[l]),c}};
50
+ let useScrollThreshold=(i,m)=>{let[u,f]=react.useState(!1),n=react.useCallback(()=>{if(i){let r=window.scrollY,e=r<i,o=r>i;f(o),m&&m(e,o);}},[i,m]);return react.useEffect(()=>{if(i){let r=dom.listenScroll(n);return n(),r}return utils.noop},[i,n]),u};
50
51
 
51
- let extendComponent=(t,o)=>Object.assign(o=>react.createElement(t,o),{...o,defaultProps:o});
52
+ let useSmoothScroll=m=>{let i=useFixedOffset();return react.useCallback((e,l,f,u,n)=>{let c;let p=!1;if(utils.isNumber(e))c=e;else if(e){let t=document.getElementById(e);t&&(c=dom.getOffsetTopSlim(t)-i.current,p=!0);}utils.isNumber(c)&&dom.scrollTo(c=c+(l||0)+(m||p?0:i.current),f,u,n);},[m,i])};
52
53
 
53
- let mergeRefs=e=>r=>{e.forEach(e=>{"function"==typeof e?e(r):null!=e&&(e.current=r);});};
54
+ let useSpinDelay=(u,c=500,i=200)=>{let[n,o]=react.useState(0),l=react.useRef();return react.useEffect(()=>{u&&0===n&&(clearTimeout(l.current),l.current=setTimeout(()=>{if(!u)return o(0);l.current=setTimeout(()=>{o(3);},i),o(2);},c),o(1)),u||2===n||(clearTimeout(l.current),o(0));},[u,n,c,i]),react.useEffect(()=>()=>clearTimeout(l.current),[]),2===n||3===n};
55
+
56
+ let useTraceUpdate=r=>{let c=react.useRef(r);react.useEffect(()=>{let e=Object.entries(r).reduce((e,[t,r])=>(c.current[t]!==r&&(e[t]=[c.current[t],r]),e),{});Object.keys(e).length>0&&console.info("[@koine/react:useTraceUpdate] changed props:",e),c.current=r;});};
57
+
58
+ let useUpdateEffect=(r,f)=>{let o=useFirstMountState();react.useEffect(()=>{if(!o)return r()},f);};
59
+
60
+ let useWindowSize=(o,n)=>{let[d,w]=react.useState(0),[m,u]=react.useState(0);return react.useEffect(()=>{let e=()=>{w(window.innerWidth),u(window.innerHeight);},i=o?dom.listenResizeDebounced(0,e,o,n):dom.listenResize(e);return e(),i},[o,n]),[d,m]};
54
61
 
62
+ exports.FaviconTags = FaviconTags;
63
+ exports.Meta = Meta;
64
+ exports.NoJs = NoJs;
55
65
  exports.classed = classed;
56
66
  exports.createUseMediaQueryWidth = createUseMediaQueryWidth;
57
67
  exports.extendComponent = extendComponent;
package/index.d.ts CHANGED
@@ -1,3 +1,28 @@
1
- export * from "./hooks";
2
- export * from "./utils";
3
- export * from "./types";
1
+ export { classed } from "./classed";
2
+ export { createUseMediaQueryWidth, type MediaQuerWidthDef, type MediaQueryWidth, } from "./createUseMediaQueryWidth";
3
+ export { type ExtendableComponent, type OverridableComponents, type WithComponents, extendComponent, } from "./extendComponent";
4
+ export { FaviconTags, type FaviconTagsProps } from "./FaviconTags";
5
+ export { mergeRefs } from "./mergeRefs";
6
+ export { Meta, type MetaProps } from "./Meta";
7
+ export { NoJs, type NoJsProps } from "./NoJs";
8
+ export type { Polymorphic } from "./Polymorphic";
9
+ export { useAsyncFn, type UseAsyncFnReturn, type UseAsyncState, } from "./useAsyncFn";
10
+ export { useFirstMountState } from "./useFirstMountState";
11
+ export { useFixedOffset } from "./useFixedOffset";
12
+ export { useFocus } from "./useFocus";
13
+ export { useInterval } from "./useInterval";
14
+ export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
15
+ export { useKeyUp } from "./useKeyUp";
16
+ export { useMeasure, type UseMeasureOptions, type UseMeasureReturn, } from "./useMeasure";
17
+ export { useMountedState } from "./useMountedState";
18
+ export { useNavigateAway, type UseNavigateAwayHandler, } from "./useNavigateAway";
19
+ export { usePrevious } from "./usePrevious";
20
+ export { usePreviousRef } from "./usePreviousRef";
21
+ export { useScrollPosition } from "./useScrollPosition";
22
+ export { useScrollThreshold } from "./useScrollThreshold";
23
+ export { useSmoothScroll } from "./useSmoothScroll";
24
+ export { useSpinDelay } from "./useSpinDelay";
25
+ export { useTraceUpdate } from "./useTraceUpdate";
26
+ export { useUpdateEffect } from "./useUpdateEffect";
27
+ export { useWindowSize } from "./useWindowSize";
28
+ export type { KoineComponentProps, KoineComponent } from "./types";
package/index.esm.js CHANGED
@@ -1,51 +1,58 @@
1
- import { useRef, useCallback, useEffect, useState, useLayoutEffect, useMemo, forwardRef, createElement } from 'react';
2
- import { isBrowser, debounce, noop, isNumber, getMediaQueryWidthResolvers, isUndefined } from '@koine/utils';
1
+ import { forwardRef, createElement, useLayoutEffect, useEffect, useState, useRef, useCallback, useMemo } from 'react';
2
+ import { isBrowser, getMediaQueryWidthResolvers, isUndefined, debounce, noop, isNumber } from '@koine/utils';
3
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
4
  import { listenResizeDebounced, $each, calculateFixedOffset, injectCss, on, listenScrollDebounced, off, listenScroll, getOffsetTopSlim, scrollTo, listenResize } from '@koine/dom';
4
5
 
5
- let useMountedState=()=>{let u=useRef(!1),n=useCallback(()=>u.current,[]);return useEffect(()=>(u.current=!0,()=>{u.current=!1;}),[]),n};
6
+ let classed=r=>{let s=r.type||r;return function(r,...a){return forwardRef(function(e,n){let o=a.map((t,s)=>{let a="";return "function"==typeof t?a=t(e):void 0!==t&&(a=t.toString()),r[s]+a}).join(""),l="string"==typeof s,i=l?{}:e;if(l)for(let t in e)t.startsWith("$")||(i[t]=e[t]);let c=o||r[0];return c=(c.match(/class="([^"]*)/)?.[1]||c)+(e?.className?" "+e?.className:""),createElement(s,{...i,className:c||void 0,ref:n})})}};
6
7
 
7
- let useAsyncFn=(o,l=[],u={loading:!1})=>{let a=useRef(0),i=useMountedState(),[d,c]=useState(u),g=useCallback((...r)=>{let t=++a.current;return d.loading||c(r=>({...r,loading:!0})),o(...r).then(r=>(i()&&t===a.current&&c({value:r,loading:!1}),r),r=>(i()&&t===a.current&&c({error:r,loading:!1}),r))},l);return [d,g]};
8
+ let useIsomorphicLayoutEffect=isBrowser?useLayoutEffect:useEffect;
8
9
 
9
- let useFirstMountState=()=>{let t=useRef(!0);return t.current?(t.current=!1,!0):t.current};
10
+ let createUseMediaQueryWidth=n=>{let a=getMediaQueryWidthResolvers(n);return function(t,n){let[o,s]=t.substring(1).split("-");isUndefined(s)&&(s=o),isUndefined(o)&&(o="min");let[d,m]=s.split("_"),u=a[o](d,m),[c,l]=useState(isUndefined(n)?null:n);return useIsomorphicLayoutEffect(()=>{let e=window.matchMedia(u),t=e=>{l(e.matches);};return (l(e.matches),e.addEventListener)?(e.addEventListener("change",t),()=>{e.removeEventListener("change",t);}):(e.addListener(t),()=>{e.removeListener(t);})},[u]),c}};
10
11
 
11
- let useIsomorphicLayoutEffect=isBrowser?useLayoutEffect:useEffect;
12
+ let extendComponent=(t,o)=>Object.assign(o=>createElement(t,o),{...o,defaultProps:o});
12
13
 
13
- let n$1=e=>{injectCss("useFixedOffset",`html{scroll-padding-top: ${e}px}`);};let useFixedOffset=i=>{let c=useRef(0);return useIsomorphicLayoutEffect(()=>{let e=()=>{let e=calculateFixedOffset();c.current=e,n$1(e);};if(e(),!ResizeObserver)return listenResizeDebounced(0,e);{let e=new ResizeObserver(e=>{let r=0;e.forEach(e=>{r+=e.contentRect.height;}),c.current=r,debounce(()=>n$1(r),400,!0)();});return $each(i||"[data-fixed]",t=>{e&&e.observe(t);}),()=>{e?.disconnect();}}},[i]),c};
14
+ let FaviconTags=({name:a,color:t,safariTabColor:o,tileColor:c,themeColor:l})=>jsxs(Fragment,{children:[jsx("link",{rel:"shortcut icon",href:"/favicon.ico",type:"image/x-icon"}),jsx("link",{rel:"apple-touch-icon",sizes:"180x180",href:"/apple-touch-icon.png"}),jsx("link",{rel:"icon",type:"image/png",sizes:"32x32",href:"/favicon-32x32.png"}),jsx("link",{rel:"icon",type:"image/png",sizes:"16x16",href:"/favicon-16x16.png"}),jsx("link",{rel:"manifest",href:"/site.webmanifest"}),jsx("link",{rel:"mask-icon",href:"/safari-pinned-tab.svg",color:o||t}),jsx("meta",{name:"apple-mobile-web-app-title",content:a}),jsx("meta",{name:"application-name",content:a}),jsx("meta",{name:"msapplication-TileColor",content:c||t}),jsx("meta",{name:"theme-color",content:l||t})]});
14
15
 
15
- let useFocus=()=>{let e=useRef(null);return [e,()=>{e.current&&e.current.focus();}]};
16
+ let mergeRefs=e=>r=>{e.forEach(e=>{"function"==typeof e?e(r):null!=e&&(e.current=r);});};
16
17
 
17
- let useInterval=(n,l,u=[])=>{let o=useRef();useEffect(()=>{o.current=n;},[n,...u]),useEffect(()=>{if(null!==l){let r=setInterval(function(){o.current&&o.current();},l);return ()=>clearInterval(r)}return noop},[l]);};
18
+ let Meta=({zoom:t})=>jsx("meta",{name:"viewport",content:`width=device-width, initial-scale=1, maximum-scale=1${t?"":", user-scalable=0"}`});
18
19
 
19
- let useKeyUp=(o,r=[])=>{useEffect(()=>on(window,"keyup",e=>{e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||o(e);}),[o,...r]);};
20
+ let NoJs=t=>jsx("script",{id:"no-js",dangerouslySetInnerHTML:{__html:'document.querySelector("html").className=document.querySelector("html").className.replace(/no-js/,"") + "js";'}});
20
21
 
21
- let e;let f=e=>{let t=[];if(!e||e===document.body)return t;let{overflow:r,overflowX:n,overflowY:l}=window.getComputedStyle(e);return [r,n,l].some(e=>"auto"===e||"scroll"===e)&&t.push(e),[...t,...f(e.parentElement)]},h=["x","y","top","bottom","left","right","width","height"],p=(e,t)=>h.every(r=>e[r]===t[r]);let useMeasure=h=>{let{scroll:d=!1}=h||{},[a,b]=useState({left:0,top:0,width:0,height:0,bottom:0,right:0,x:0,y:0}),g=useRef([null,null,null,a]),v=useRef(!1);useEffect(()=>(v.current=!0,()=>void(v.current=!1)),[]);let[w,,y]=useMemo(()=>{let e=(...e)=>{let[t,,,r]=g.current;if(!t)return;let n=t.getBoundingClientRect();Object.freeze(n),v.current&&!p(r,n)&&(g.current[3]=n,b(n));},t=debounce(e);return [e,t,t]},[b]);function x(){let[,e,t]=g.current;e&&(e.forEach(e=>off(e,"scroll",y)),g.current[1]=null),t&&(t.disconnect(),g.current[2]=null);}function z(){let[t,r]=g.current;t&&!e&&ResizeObserver&&(e=new ResizeObserver(y),g.current[2]=e,e.observe(t),d&&r&&r.forEach(e=>on(e,"scroll",y,{capture:!0,passive:!0})));}return useEffect(()=>d?listenScrollDebounced(0,w,100):noop,[d,w]),useEffect(()=>listenResizeDebounced(0,w,100),[w]),useEffect(()=>{x(),z();},[d]),useEffect(()=>(w(),x),[]),[e=>{e&&e!==g.current[0]&&(x(),g.current[0]=e,g.current[1]=f(e),z());},a,w]};
22
+ let useMountedState=()=>{let u=useRef(!1),n=useCallback(()=>u.current,[]);return useEffect(()=>(u.current=!0,()=>{u.current=!1;}),[]),n};
22
23
 
23
- let useNavigateAway=o=>{let n=useRef();useEffect(()=>{n.current=e=>{let r=o(e);return (r&&e.preventDefault(),"string"==typeof r)?e.returnValue=r:e.defaultPrevented?e.returnValue="":void 0};},[o]),useEffect(()=>on(window,"beforeunload",e=>n.current?.(e)),[]);};
24
+ let useAsyncFn=(o,u=[],l={loading:!1})=>{let a=useRef(0),d=useMountedState(),[i,c]=useState(l),g=useCallback((...e)=>{let t=++a.current;return i.loading||c(e=>({...e,loading:!0})),o(...e).then(e=>(d()&&t===a.current&&c({value:e,loading:!1}),e),e=>(d()&&t===a.current&&c({error:e,loading:!1}),e))},u);return [i,g]};
24
25
 
25
- let usePrevious=(r,t)=>{let[o,u]=useState([r,t]);return o[1]!==r&&u([o[1],r]),o[0]};
26
+ let useFirstMountState=()=>{let r=useRef(!0);return r.current?(r.current=!1,!0):r.current};
26
27
 
27
- let usePreviousRef=t=>{let u=useRef();return useEffect(()=>{u.current=t;}),u.current};
28
+ let n$1=e=>{injectCss("useFixedOffset",`html{scroll-padding-top: ${e}px}`);};let useFixedOffset=i=>{let l=useRef(0);return useIsomorphicLayoutEffect(()=>{let e=()=>{let e=calculateFixedOffset();l.current=e,n$1(e);};if(e(),!ResizeObserver)return listenResizeDebounced(0,e);{let e=new ResizeObserver(e=>{let r=0;e.forEach(e=>{r+=e.contentRect.height;}),l.current=r,debounce(()=>n$1(r),400,!0)();});return $each(i||"[data-fixed]",t=>{e&&e.observe(t);}),()=>{e?.disconnect();}}},[i]),l};
28
29
 
29
- let l={x:0,y:0},n=r=>r?.getBoundingClientRect(),u=(r,e)=>{if(!isBrowser)return l;if(!e)return {x:window.scrollX,y:window.scrollY};let o=n(r?.current||document.body),u=n(e.current);return o?u?{x:(u.x||0)-(o.x||0),y:(u.y||0)-(o.y||0)}:{x:o.left,y:o.top}:l};let useScrollPosition=(l,n=[],i,c,m)=>{let f=useRef(u(null,c)),s=null,y=()=>{let r=u(i,c);l(r,f.current),f.current=r,s=null;};useIsomorphicLayoutEffect(()=>{if(!isBrowser)return;let r=listenScroll(()=>{m?null===s&&(s=window.setTimeout(y,m)):y();},c?.current);return ()=>{r(),s&&clearTimeout(s);}},n);};
30
+ let useFocus=()=>{let r=useRef(null);return [r,()=>{r.current&&r.current.focus();}]};
30
31
 
31
- let useScrollThreshold=(i,m)=>{let[n,f]=useState(!1),u=useCallback(()=>{if(i){let r=window.scrollY,o=r<i,e=r>i;f(e),m&&m(o,e);}},[i,m]);return useEffect(()=>{if(i){let r=listenScroll(u);return u(),r}return noop},[i,u]),n};
32
+ let useInterval=(n,l,u=[])=>{let o=useRef();useEffect(()=>{o.current=n;},[n,...u]),useEffect(()=>{if(null!==l){let r=setInterval(function(){o.current&&o.current();},l);return ()=>clearInterval(r)}return noop},[l]);};
32
33
 
33
- let useSmoothScroll=i=>{let l=useFixedOffset();return useCallback((e,m,f,n,u)=>{let c;let p=!1;if(isNumber(e))c=e;else if(e){let t=document.getElementById(e);t&&(c=getOffsetTopSlim(t)-l.current,p=!0);}isNumber(c)&&scrollTo(c=c+(m||0)+(i||p?0:l.current),f,n,u);},[i,l])};
34
+ let useKeyUp=(o,r=[])=>{useEffect(()=>on(window,"keyup",e=>{e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||o(e);}),[o,...r]);};
34
35
 
35
- let useSpinDelay=(u,c=500,i=200)=>{let[n,o]=useState(0),m=useRef();return useEffect(()=>{u&&0===n&&(clearTimeout(m.current),m.current=setTimeout(()=>{if(!u)return o(0);m.current=setTimeout(()=>{o(3);},i),o(2);},c),o(1)),u||2===n||(clearTimeout(m.current),o(0));},[u,n,c,i]),useEffect(()=>()=>clearTimeout(m.current),[]),2===n||3===n};
36
+ let e;let m=e=>{let t=[];if(!e||e===document.body)return t;let{overflow:r,overflowX:n,overflowY:u}=window.getComputedStyle(e);return [r,n,u].some(e=>"auto"===e||"scroll"===e)&&t.push(e),[...t,...m(e.parentElement)]},p=["x","y","top","bottom","left","right","width","height"],d=(e,t)=>p.every(r=>e[r]===t[r]);let useMeasure=p=>{let{scroll:h=!1}=p||{},[a,b]=useState({left:0,top:0,width:0,height:0,bottom:0,right:0,x:0,y:0}),g=useRef([null,null,null,a]),v=useRef(!1);useEffect(()=>(v.current=!0,()=>void(v.current=!1)),[]);let[w,,y]=useMemo(()=>{let e=(...e)=>{let[t,,,r]=g.current;if(!t)return;let n=t.getBoundingClientRect();Object.freeze(n),v.current&&!d(r,n)&&(g.current[3]=n,b(n));},t=debounce(e);return [e,t,t]},[b]);function x(){let[,e,t]=g.current;e&&(e.forEach(e=>off(e,"scroll",y)),g.current[1]=null),t&&(t.disconnect(),g.current[2]=null);}function z(){let[t,r]=g.current;t&&!e&&ResizeObserver&&(e=new ResizeObserver(y),g.current[2]=e,e.observe(t),h&&r&&r.forEach(e=>on(e,"scroll",y,{capture:!0,passive:!0})));}return useEffect(()=>h?listenScrollDebounced(0,w,100):noop,[h,w]),useEffect(()=>listenResizeDebounced(0,w,100),[w]),useEffect(()=>{x(),z();},[h]),useEffect(()=>(w(),x),[]),[e=>{e&&e!==g.current[0]&&(x(),g.current[0]=e,g.current[1]=m(e),z());},a,w]};
36
37
 
37
- let useTraceUpdate=t=>{let c=useRef(t);useEffect(()=>{let e=Object.entries(t).reduce((e,[r,t])=>(c.current[r]!==t&&(e[r]=[c.current[r],t]),e),{});Object.keys(e).length>0&&console.info("[@koine/react:useTraceUpdate] changed props:",e),c.current=t;});};
38
+ let useNavigateAway=a=>{let o=useRef();useEffect(()=>{o.current=e=>{let t=a(e);return (t&&e.preventDefault(),"string"==typeof t)?e.returnValue=t:e.defaultPrevented?e.returnValue="":void 0};},[a]),useEffect(()=>on(window,"beforeunload",e=>o.current?.(e)),[]);};
38
39
 
39
- let useUpdateEffect=(r,o)=>{let f=useFirstMountState();useEffect(()=>{if(!f)return r()},o);};
40
+ let usePrevious=(r,t)=>{let[o,u]=useState([r,t]);return o[1]!==r&&u([o[1],r]),o[0]};
40
41
 
41
- let useWindowSize=(n,o)=>{let[d,m]=useState(0),[w,l]=useState(0);return useEffect(()=>{let e=()=>{m(window.innerWidth),l(window.innerHeight);},r=n?listenResizeDebounced(0,e,n,o):listenResize(e);return e(),r},[n,o]),[d,w]};
42
+ let usePreviousRef=t=>{let u=useRef();return useEffect(()=>{u.current=t;}),u.current};
42
43
 
43
- let classed=r=>{let n=r.type||r;return function(r,...o){return forwardRef(function(e,s){let a=o.map((t,n)=>{let o="";return "function"==typeof t?o=t(e):void 0!==t&&(o=t.toString()),r[n]+o}).join(""),i="string"==typeof n,l=i?{}:e;if(i)for(let t in e)t.startsWith("$")||(l[t]=e[t]);let c=a||r[0];return c=(c.match(/class="([^"]*)/)?.[1]||c)+(e?.className?" "+e?.className:""),createElement(n,{...l,className:c||void 0,ref:s})})}};
44
+ let l={x:0,y:0},n=t=>t?.getBoundingClientRect(),u=(t,e)=>{if(!isBrowser)return l;if(!e)return {x:window.scrollX,y:window.scrollY};let o=n(t?.current||document.body),u=n(e.current);return o?u?{x:(u.x||0)-(o.x||0),y:(u.y||0)-(o.y||0)}:{x:o.left,y:o.top}:l};let useScrollPosition=(l,n=[],i,c,m)=>{let f=useRef(u(null,c)),s=null,d=()=>{let t=u(i,c);l(t,f.current),f.current=t,s=null;};useIsomorphicLayoutEffect(()=>{if(!isBrowser)return;let t=listenScroll(()=>{m?null===s&&(s=window.setTimeout(d,m)):d();},c?.current);return ()=>{t(),s&&clearTimeout(s);}},n);};
44
45
 
45
- let createUseMediaQueryWidth=i=>{let o=getMediaQueryWidthResolvers(i);return function(t,i){let[s,a]=t.substring(1).split("-");isUndefined(a)&&(a=s),isUndefined(s)&&(s="min");let[m,d]=a.split("_"),l=o[s](m,d),[c,u]=useState(isUndefined(i)?null:i);return useIsomorphicLayoutEffect(()=>{let e=window.matchMedia(l),t=e=>{u(e.matches);};return (u(e.matches),e.addEventListener)?(e.addEventListener("change",t),()=>{e.removeEventListener("change",t);}):(e.addListener(t),()=>{e.removeListener(t);})},[l]),c}};
46
+ let useScrollThreshold=(i,m)=>{let[u,f]=useState(!1),n=useCallback(()=>{if(i){let r=window.scrollY,e=r<i,o=r>i;f(o),m&&m(e,o);}},[i,m]);return useEffect(()=>{if(i){let r=listenScroll(n);return n(),r}return noop},[i,n]),u};
46
47
 
47
- let extendComponent=(t,o)=>Object.assign(o=>createElement(t,o),{...o,defaultProps:o});
48
+ let useSmoothScroll=m=>{let i=useFixedOffset();return useCallback((e,l,f,u,n)=>{let c;let p=!1;if(isNumber(e))c=e;else if(e){let t=document.getElementById(e);t&&(c=getOffsetTopSlim(t)-i.current,p=!0);}isNumber(c)&&scrollTo(c=c+(l||0)+(m||p?0:i.current),f,u,n);},[m,i])};
48
49
 
49
- let mergeRefs=e=>r=>{e.forEach(e=>{"function"==typeof e?e(r):null!=e&&(e.current=r);});};
50
+ let useSpinDelay=(u,c=500,i=200)=>{let[n,o]=useState(0),l=useRef();return useEffect(()=>{u&&0===n&&(clearTimeout(l.current),l.current=setTimeout(()=>{if(!u)return o(0);l.current=setTimeout(()=>{o(3);},i),o(2);},c),o(1)),u||2===n||(clearTimeout(l.current),o(0));},[u,n,c,i]),useEffect(()=>()=>clearTimeout(l.current),[]),2===n||3===n};
51
+
52
+ let useTraceUpdate=r=>{let c=useRef(r);useEffect(()=>{let e=Object.entries(r).reduce((e,[t,r])=>(c.current[t]!==r&&(e[t]=[c.current[t],r]),e),{});Object.keys(e).length>0&&console.info("[@koine/react:useTraceUpdate] changed props:",e),c.current=r;});};
53
+
54
+ let useUpdateEffect=(r,f)=>{let o=useFirstMountState();useEffect(()=>{if(!o)return r()},f);};
55
+
56
+ let useWindowSize=(o,n)=>{let[d,w]=useState(0),[m,u]=useState(0);return useEffect(()=>{let e=()=>{w(window.innerWidth),u(window.innerHeight);},i=o?listenResizeDebounced(0,e,o,n):listenResize(e);return e(),i},[o,n]),[d,m]};
50
57
 
51
- export { classed, createUseMediaQueryWidth, extendComponent, mergeRefs, useAsyncFn, useFirstMountState, useFixedOffset, useFocus, useInterval, useIsomorphicLayoutEffect, useKeyUp, useMeasure, useMountedState, useNavigateAway, usePrevious, usePreviousRef, useScrollPosition, useScrollThreshold, useSmoothScroll, useSpinDelay, useTraceUpdate, useUpdateEffect, useWindowSize };
58
+ export { FaviconTags, Meta, NoJs, classed, createUseMediaQueryWidth, extendComponent, mergeRefs, useAsyncFn, useFirstMountState, useFixedOffset, useFocus, useInterval, useIsomorphicLayoutEffect, useKeyUp, useMeasure, useMountedState, useNavigateAway, usePrevious, usePreviousRef, useScrollPosition, useScrollThreshold, useSmoothScroll, useSpinDelay, useTraceUpdate, useUpdateEffect, useWindowSize };
package/index.js CHANGED
@@ -1,3 +1,26 @@
1
- export * from "./hooks";
2
- export * from "./utils";
3
- export * from "./types";
1
+ export { classed } from "./classed";
2
+ export { createUseMediaQueryWidth, } from "./createUseMediaQueryWidth";
3
+ export { extendComponent, } from "./extendComponent";
4
+ export { FaviconTags } from "./FaviconTags";
5
+ export { mergeRefs } from "./mergeRefs";
6
+ export { Meta } from "./Meta";
7
+ export { NoJs } from "./NoJs";
8
+ export { useAsyncFn, } from "./useAsyncFn";
9
+ export { useFirstMountState } from "./useFirstMountState";
10
+ export { useFixedOffset } from "./useFixedOffset";
11
+ export { useFocus } from "./useFocus";
12
+ export { useInterval } from "./useInterval";
13
+ export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
14
+ export { useKeyUp } from "./useKeyUp";
15
+ export { useMeasure, } from "./useMeasure";
16
+ export { useMountedState } from "./useMountedState";
17
+ export { useNavigateAway, } from "./useNavigateAway";
18
+ export { usePrevious } from "./usePrevious";
19
+ export { usePreviousRef } from "./usePreviousRef";
20
+ export { useScrollPosition } from "./useScrollPosition";
21
+ export { useScrollThreshold } from "./useScrollThreshold";
22
+ export { useSmoothScroll } from "./useSmoothScroll";
23
+ export { useSpinDelay } from "./useSpinDelay";
24
+ export { useTraceUpdate } from "./useTraceUpdate";
25
+ export { useUpdateEffect } from "./useUpdateEffect";
26
+ export { useWindowSize } from "./useWindowSize";
package/mergeRefs.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare let mergeRefs: <T = Element>(refs: (import("react").MutableRefObject<T> | import("react").LegacyRef<T>)[]) => (instance: T | null) => void;
2
+ export default mergeRefs;
package/mergeRefs.js ADDED
@@ -0,0 +1,13 @@
1
+ export let mergeRefs = (refs) => {
2
+ return (value) => {
3
+ refs.forEach((ref) => {
4
+ if (typeof ref === "function") {
5
+ ref(value);
6
+ }
7
+ else if (ref != null) {
8
+ ref.current = value;
9
+ }
10
+ });
11
+ };
12
+ };
13
+ export default mergeRefs;