@opensite/hooks 2.0.0 → 2.0.2

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 (87) hide show
  1. package/dist/browser/opensite-hooks.umd.cjs +1 -1
  2. package/dist/browser/opensite-hooks.umd.js +1 -1
  3. package/dist/browser/opensite-hooks.umd.js.map +1 -1
  4. package/dist/core/index.cjs +7 -0
  5. package/dist/core/index.d.ts +13 -0
  6. package/dist/core/index.js +7 -0
  7. package/dist/core/useOpenGraphExtractor.cjs +59 -0
  8. package/dist/core/useOpenGraphExtractor.d.ts +64 -0
  9. package/dist/core/useOpenGraphExtractor.js +59 -0
  10. package/dist/core/useWebsiteExtractorBase.cjs +153 -0
  11. package/dist/core/useWebsiteExtractorBase.d.ts +9 -0
  12. package/dist/core/useWebsiteExtractorBase.js +153 -0
  13. package/dist/core/useWebsiteLinksExtractor.cjs +16 -0
  14. package/dist/core/useWebsiteLinksExtractor.d.ts +14 -0
  15. package/dist/core/useWebsiteLinksExtractor.js +16 -0
  16. package/dist/core/useWebsiteMetaExtractor.cjs +20 -0
  17. package/dist/core/useWebsiteMetaExtractor.d.ts +12 -0
  18. package/dist/core/useWebsiteMetaExtractor.js +20 -0
  19. package/dist/core/useWebsiteRssExtractor.cjs +15 -0
  20. package/dist/core/useWebsiteRssExtractor.d.ts +12 -0
  21. package/dist/core/useWebsiteRssExtractor.js +15 -0
  22. package/dist/core/useWebsiteSchemaExtractor.cjs +15 -0
  23. package/dist/core/useWebsiteSchemaExtractor.d.ts +11 -0
  24. package/dist/core/useWebsiteSchemaExtractor.js +15 -0
  25. package/dist/core/websiteExtractorService.cjs +66 -0
  26. package/dist/core/websiteExtractorService.d.ts +3 -0
  27. package/dist/core/websiteExtractorService.js +66 -0
  28. package/dist/core/websiteExtractorTypes.cjs +25 -0
  29. package/dist/core/websiteExtractorTypes.d.ts +65 -0
  30. package/dist/core/websiteExtractorTypes.js +25 -0
  31. package/package.json +36 -1
  32. package/dist/hooks/index.cjs +0 -16
  33. package/dist/hooks/index.d.ts +0 -24
  34. package/dist/hooks/index.js +0 -16
  35. package/dist/hooks/useBoolean.cjs +0 -1
  36. package/dist/hooks/useBoolean.d.ts +0 -2
  37. package/dist/hooks/useBoolean.js +0 -1
  38. package/dist/hooks/useCopyToClipboard.cjs +0 -1
  39. package/dist/hooks/useCopyToClipboard.d.ts +0 -2
  40. package/dist/hooks/useCopyToClipboard.js +0 -1
  41. package/dist/hooks/useDebounceCallback.cjs +0 -1
  42. package/dist/hooks/useDebounceCallback.d.ts +0 -2
  43. package/dist/hooks/useDebounceCallback.js +0 -1
  44. package/dist/hooks/useDebounceValue.cjs +0 -1
  45. package/dist/hooks/useDebounceValue.d.ts +0 -2
  46. package/dist/hooks/useDebounceValue.js +0 -1
  47. package/dist/hooks/useEventListener.cjs +0 -1
  48. package/dist/hooks/useEventListener.d.ts +0 -1
  49. package/dist/hooks/useEventListener.js +0 -1
  50. package/dist/hooks/useHover.cjs +0 -1
  51. package/dist/hooks/useHover.d.ts +0 -1
  52. package/dist/hooks/useHover.js +0 -1
  53. package/dist/hooks/useIsClient.cjs +0 -1
  54. package/dist/hooks/useIsClient.d.ts +0 -1
  55. package/dist/hooks/useIsClient.js +0 -1
  56. package/dist/hooks/useIsomorphicLayoutEffect.cjs +0 -1
  57. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +0 -1
  58. package/dist/hooks/useIsomorphicLayoutEffect.js +0 -1
  59. package/dist/hooks/useLocalStorage.cjs +0 -1
  60. package/dist/hooks/useLocalStorage.d.ts +0 -2
  61. package/dist/hooks/useLocalStorage.js +0 -1
  62. package/dist/hooks/useMap.cjs +0 -1
  63. package/dist/hooks/useMap.d.ts +0 -2
  64. package/dist/hooks/useMap.js +0 -1
  65. package/dist/hooks/useMediaQuery.cjs +0 -1
  66. package/dist/hooks/useMediaQuery.d.ts +0 -2
  67. package/dist/hooks/useMediaQuery.js +0 -1
  68. package/dist/hooks/useOnClickOutside.cjs +0 -1
  69. package/dist/hooks/useOnClickOutside.d.ts +0 -1
  70. package/dist/hooks/useOnClickOutside.js +0 -1
  71. package/dist/hooks/usePrevious.cjs +0 -1
  72. package/dist/hooks/usePrevious.d.ts +0 -1
  73. package/dist/hooks/usePrevious.js +0 -1
  74. package/dist/hooks/useResizeObserver.cjs +0 -1
  75. package/dist/hooks/useResizeObserver.d.ts +0 -1
  76. package/dist/hooks/useResizeObserver.js +0 -1
  77. package/dist/hooks/useSessionStorage.cjs +0 -1
  78. package/dist/hooks/useSessionStorage.d.ts +0 -2
  79. package/dist/hooks/useSessionStorage.js +0 -1
  80. package/dist/hooks/useThrottle.cjs +0 -1
  81. package/dist/hooks/useThrottle.d.ts +0 -2
  82. package/dist/hooks/useThrottle.js +0 -1
  83. package/dist/test/setup.cjs +0 -98
  84. package/dist/test/setup.d.ts +0 -5
  85. package/dist/test/setup.js +0 -98
  86. package/dist/test/utils.cjs +0 -73
  87. package/dist/test/utils.js +0 -73
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).OpensiteHooks={},e.React)}(this,function(e,t){"use strict";const n="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;function r(e,r,u={}){const c=t.useRef(e),o=t.useRef(null),s=t.useRef(null),i=t.useRef(null),a=u.leading??!1,l=u.trailing??!0,f=u.maxWait,d=Math.max(0,r);n(()=>{c.current=e},[e]);const p=t.useCallback(()=>{o.current&&(clearTimeout(o.current),o.current=null),s.current&&(clearTimeout(s.current),s.current=null)},[]),m=t.useCallback(()=>{if(!i.current)return;const e=i.current;i.current=null,c.current(...e)},[]),y=t.useCallback((...e)=>{i.current=e;if(a&&null===o.current&&null===s.current&&m(),o.current&&clearTimeout(o.current),l&&(o.current=setTimeout(()=>{o.current=null,i.current&&m(),s.current&&(clearTimeout(s.current),s.current=null)},d)),null!=f&&l&&!s.current){const e=Math.max(0,f);s.current=setTimeout(()=>{s.current=null,o.current&&(clearTimeout(o.current),o.current=null),i.current&&m()},e)}},[m,a,l,f,d]),w=t.useCallback(()=>{p(),i.current=null},[p]),v=t.useCallback(()=>{i.current&&(p(),m())},[p,m]);return t.useEffect(()=>()=>w(),[w]),{debouncedCallback:y,cancel:w,flush:v}}function u(e,r,u,c){const o=t.useRef(r);n(()=>{o.current=r},[r]),t.useEffect(()=>{const t="undefined"!=typeof Window&&u instanceof Window,n="undefined"!=typeof Document&&u instanceof Document,r=void 0===u?"undefined"!=typeof window?window:null:t||n||"undefined"!=typeof HTMLElement&&u instanceof HTMLElement?u:(s=u)&&"object"==typeof s&&"current"in s?u.current:null;var s;if(!(null==r?void 0:r.addEventListener))return;const i=e=>{const t=o.current;"function"==typeof t?t(e):t.handleEvent(e)};return r.addEventListener(e,i,c),()=>{r.removeEventListener(e,i,c)}},[e,u,c])}e.useBoolean=function(e=!1){const[n,r]=t.useState(e),u=t.useCallback(()=>r(!0),[]),c=t.useCallback(()=>r(!1),[]),o=t.useCallback(()=>r(e=>!e),[]);return{value:n,setValue:r,setTrue:u,setFalse:c,toggle:o}},e.useCopyToClipboard=function(e={}){const n=e.resetDelay??2e3,r=t.useRef(null),[u,c]=t.useState(null),o=t.useMemo(()=>!("undefined"==typeof navigator||!navigator.clipboard)||"undefined"!=typeof document&&("function"==typeof document.queryCommandSupported&&document.queryCommandSupported("copy")),[]),s=t.useCallback(()=>{r.current&&clearTimeout(r.current),r.current=setTimeout(()=>{c(null)},n)},[n]),i=t.useCallback(async e=>{if(!o)return!1;const t="undefined"!=typeof navigator&&!!navigator.clipboard;try{if(t)await navigator.clipboard.writeText(e);else if("undefined"!=typeof document){const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.focus(),t.select();const n=document.execCommand("copy");if(document.body.removeChild(t),!n)return!1}return c(e),s(),!0}catch{return!1}},[o,s]);return t.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]),{copy:i,copiedText:u,isSupported:o}},e.useDebounceCallback=r,e.useDebounceValue=function(e,n,u){const[c,o]=t.useState(e),{debouncedCallback:s,cancel:i}=r(e=>{o(e)},n,u);return t.useEffect(()=>{s(e)},[s,e]),t.useEffect(()=>()=>i(),[i]),c},e.useEventListener=u,e.useHover=function(e){const[n,r]=t.useState(!1),c=t.useCallback(()=>{r(!0)},[]),o=t.useCallback(()=>{r(!1)},[]);return u("pointerenter",c,e),u("pointerleave",o,e),n},e.useIsClient=function(){const[e,n]=t.useState(!1);return t.useEffect(()=>{n(!0)},[]),e},e.useIsomorphicLayoutEffect=n,e.useLocalStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:c=JSON.stringify,deserialize:o=JSON.parse,listenToStorageChanges:s=!0}=r,i=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return i.current;if(!u)return i.current;try{const t=window.localStorage.getItem(e);return t?o(t):i.current}catch{return i.current}},[o,u,e]),[l,f]=t.useState(()=>a()),d=t.useCallback(t=>{f(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.localStorage.setItem(e,c(r))}catch{}return r})},[e,c]);return t.useEffect(()=>{f(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{f(o(t.newValue))}catch{f(i.current)}else f(i.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[o,e,s]),[l,d]},e.useMap=function(e){const[n,r]=t.useState(()=>e instanceof Map||Array.isArray(e)?new Map(e):new Map),u=t.useRef(n);t.useEffect(()=>{u.current=n},[n]);const c=t.useMemo(()=>({set:(e,t)=>{r(n=>{const r=new Map(n);return r.set(e,t),r})},setAll:e=>{r((Map,new Map(e)))},remove:e=>{r(t=>{const n=new Map(t);return n.delete(e),n})},clear:()=>r(new Map),get:e=>u.current.get(e),has:e=>u.current.has(e)}),[]);return[n,c]},e.useMediaQuery=function(e,n={}){const[r,u]=t.useState(()=>"undefined"==typeof window||"function"!=typeof window.matchMedia?n.defaultValue??!1:window.matchMedia(e).matches);return t.useEffect(()=>{if("undefined"==typeof window||"function"!=typeof window.matchMedia)return;const t=window.matchMedia(e),n=e=>{u(e.matches)};return u(t.matches),t.addEventListener?(t.addEventListener("change",n),()=>t.removeEventListener("change",n)):(t.addListener(n),()=>t.removeListener(n))},[e]),r},e.useOnClickOutside=function(e,n,r="mousedown",u){const c=t.useRef(n);t.useEffect(()=>{c.current=n},[n]),t.useEffect(()=>{if("undefined"==typeof document)return;const t=Array.isArray(e)?e:[e],n=e=>{const n=e.target;if("undefined"==typeof Node||!(n instanceof Node))return;t.some(e=>{const t=e.current;return!!t&&t.contains(n)})||c.current(e)};return document.addEventListener(r,n,u),()=>{document.removeEventListener(r,n,u)}},[r,u,e])},e.usePrevious=function(e){const n=t.useRef();return t.useEffect(()=>{n.current=e},[e]),n.current},e.useResizeObserver=function(e,r,u){const c=t.useRef(r),o=t.useRef(null),[s,i]=t.useState(null);return n(()=>{c.current=r},[r]),t.useEffect(()=>{if("undefined"==typeof ResizeObserver)return;const t="undefined"!=typeof Element&&e instanceof Element?e:(n=e)&&"object"==typeof n&&"current"in n?e.current:null;var n;if(!t)return;const r=new ResizeObserver(e=>{const t=e[0];o.current=t,c.current?c.current(t):i(t)});return r.observe(t,u),()=>r.disconnect()},[u,e]),c.current?o.current:s},e.useSessionStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:c=JSON.stringify,deserialize:o=JSON.parse,listenToStorageChanges:s=!1}=r,i=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return i.current;if(!u)return i.current;try{const t=window.sessionStorage.getItem(e);return t?o(t):i.current}catch{return i.current}},[o,u,e]),[l,f]=t.useState(()=>a()),d=t.useCallback(t=>{f(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.sessionStorage.setItem(e,c(r))}catch{}return r})},[e,c]);return t.useEffect(()=>{f(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{f(o(t.newValue))}catch{f(i.current)}else f(i.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[o,e,s]),[l,d]},e.useThrottle=function(e,n,r={}){const u=r.leading??!0,c=r.trailing??!0,o=Math.max(0,n),[s,i]=t.useState(e),a=t.useRef(0),l=t.useRef(null),f=t.useRef(null);return t.useEffect(()=>{if(0===o)return void i(e);const t=Date.now();if(0===a.current)return a.current=t,u?void i(e):void(c&&!l.current&&(f.current=e,l.current=setTimeout(()=>{l.current=null,null!==f.current&&(i(f.current),f.current=null,a.current=Date.now())},o)));const n=t-a.current;if(n>=o&&u)return i(e),a.current=t,void(f.current=null);if(c&&(f.current=e,!l.current)){const e=Math.max(o-n,0);l.current=setTimeout(()=>{l.current=null,null!==f.current&&(i(f.current),f.current=null,a.current=Date.now())},e)}},[u,c,e,o]),t.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]),s},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).OpensiteHooks={},e.React)}(this,function(e,t){"use strict";const n="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;function r(e,r,u={}){const o=t.useRef(e),i=t.useRef(null),s=t.useRef(null),c=t.useRef(null),a=u.leading??!1,l=u.trailing??!0,d=u.maxWait,f=Math.max(0,r);n(()=>{o.current=e},[e]);const p=t.useCallback(()=>{i.current&&(clearTimeout(i.current),i.current=null),s.current&&(clearTimeout(s.current),s.current=null)},[]),m=t.useCallback(()=>{if(!c.current)return;const e=c.current;c.current=null,o.current(...e)},[]),v=t.useCallback((...e)=>{c.current=e;if(a&&null===i.current&&null===s.current&&m(),i.current&&clearTimeout(i.current),l&&(i.current=setTimeout(()=>{i.current=null,c.current&&m(),s.current&&(clearTimeout(s.current),s.current=null)},f)),null!=d&&l&&!s.current){const e=Math.max(0,d);s.current=setTimeout(()=>{s.current=null,i.current&&(clearTimeout(i.current),i.current=null),c.current&&m()},e)}},[m,a,l,d,f]),y=t.useCallback(()=>{p(),c.current=null},[p]),g=t.useCallback(()=>{c.current&&(p(),m())},[p,m]);return t.useEffect(()=>()=>y(),[y]),{debouncedCallback:v,cancel:y,flush:g}}function u(e,n,u){const[o,i]=t.useState(e),{debouncedCallback:s,cancel:c}=r(e=>{i(e)},n,u);return t.useEffect(()=>{s(e)},[s,e]),t.useEffect(()=>()=>c(),[c]),o}function o(e,r,u,o){const i=t.useRef(r);n(()=>{i.current=r},[r]),t.useEffect(()=>{const t="undefined"!=typeof Window&&u instanceof Window,n="undefined"!=typeof Document&&u instanceof Document,r=void 0===u?"undefined"!=typeof window?window:null:t||n||"undefined"!=typeof HTMLElement&&u instanceof HTMLElement?u:(s=u)&&"object"==typeof s&&"current"in s?u.current:null;var s;if(!(null==r?void 0:r.addEventListener))return;const c=e=>{const t=i.current;"function"==typeof t?t(e):t.handleEvent(e)};return r.addEventListener(e,c,o),()=>{r.removeEventListener(e,c,o)}},[e,u,o])}function i(){const[e,n]=t.useState(!1);return t.useEffect(()=>{n(!0)},[]),e}function s(e){const[n,r]=t.useState(()=>e instanceof Map||Array.isArray(e)?new Map(e):new Map),u=t.useRef(n);t.useEffect(()=>{u.current=n},[n]);const o=t.useMemo(()=>({set:(e,t)=>{r(n=>{const r=new Map(n);return r.set(e,t),r})},setAll:e=>{r((Map,new Map(e)))},remove:e=>{r(t=>{const n=new Map(t);return n.delete(e),n})},clear:()=>r(new Map),get:e=>u.current.get(e),has:e=>u.current.has(e)}),[]);return[n,o]}const c="https://octane.buzz";function a(e){const t=function(e){return e.replace(/\/+$/,"")}(e.baseUrl??c),n=new URLSearchParams;return e.apiKey&&n.set("api_key",e.apiKey),n.set("url",e.url),`${t}/api/v1/extract/${e.endpoint}?${n.toString()}`}async function l(e){var t;if(!e.url||0===e.url.trim().length)return{ok:!1,error:{message:"URL is required."}};const n=a(e);try{const t=await fetch(n,{method:"GET",signal:e.signal});let r=null;try{r=await t.json()}catch{r=null}if(!t.ok){const e=r;return{ok:!1,error:{message:(null==e?void 0:e.error)??`Request failed with status ${t.status}.`,status:(null==e?void 0:e.status)??t.status,raw:r}}}return{ok:!0,response:r}}catch(r){return(null==(t=e.signal)?void 0:t.aborted)?{ok:!1,error:{message:"Request aborted."}}:{ok:!1,error:{message:r instanceof Error?r.message:"Request failed unexpectedly.",raw:r}}}}function d(e){const{endpoint:n,options:o,selectData:a,shouldSkip:d}=e,f=i(),[p,m]=t.useState({loading:!1}),[,v]=s(),y=o.cache??true,g=o.enabled??true,b=o.debounceMs??250,w=o.refreshDebounceMs??150,h=u(t.useMemo(()=>{var e;return(null==(e=o.url)?void 0:e.trim())??""},[o.url]),b),E=t.useRef(0),k=t.useRef(0),[C,T]=t.useState(0),{debouncedCallback:S,cancel:R}=r(()=>{E.current+=1,T(E.current)},w),M=t.useCallback(()=>{S()},[S]);t.useEffect(()=>()=>R(),[R]);const x=t.useMemo(()=>{if(!h)return"";const e=o.baseUrl??c,t=o.apiKey??"";return`${n}:${e}:${t}:${h}`},[n,o.apiKey,o.baseUrl,h]),L=t.useRef(null);return t.useEffect(()=>{var e;if(!f)return;if(!g||!h)return void m({loading:!1});if(null==d?void 0:d(h))return void m({loading:!1});const t=C!==k.current;if(t&&(k.current=C),y&&!t){const e=v.get(x);if(e)return void m({loading:!1,data:e.data,raw:e.raw,meta:e.meta})}null==(e=L.current)||e.abort();const r=new AbortController;return L.current=r,m(e=>({...e,loading:!0,error:void 0})),l({endpoint:n,url:h,apiKey:o.apiKey,baseUrl:o.baseUrl,signal:r.signal}).then(e=>{if(r.signal.aborted)return;if(!e.ok)return void m(t=>({...t,loading:!1,error:e.error}));const t=e.response,n=function(e){const{requestedUrl:t,finalUrl:n,url:r,normalizedUrl:u,status:o,contentType:i,fetchedAt:s,bodyBytes:c,bodyTruncated:a,maxBodyBytes:l,cache:d}=e;return{requestedUrl:t,finalUrl:n,url:r,normalizedUrl:u,status:o,contentType:i,fetchedAt:s,bodyBytes:c,bodyTruncated:a,maxBodyBytes:l,cache:d}}(t),u=function(e){const{requestedUrl:t,finalUrl:n,url:r,normalizedUrl:u,status:o,contentType:i,fetchedAt:s,bodyBytes:c,bodyTruncated:a,maxBodyBytes:l,cache:d,...f}=e;return f}(t),o=a(u,t,n);y&&v.set(x,{data:o,raw:t,meta:n}),m({loading:!1,data:o,raw:t,meta:n})}).catch(e=>{r.signal.aborted||m(t=>({...t,loading:!1,error:{message:e instanceof Error?e.message:"Request failed unexpectedly.",raw:e}}))}),()=>{r.abort()}},[v,y,h,g,n,f,o.apiKey,o.baseUrl,x,C,a,d]),t.useMemo(()=>({...p,refresh:M}),[M,p])}const f=[/search\.google\.com\/local\/reviews/i,/google\.com\/maps\/place/i,/maps\.google\.com/i,/opentable\.com/i],p=(...e)=>{for(const t of e)if("string"==typeof t&&t.trim().length>0)return t},m=e=>{if(e)try{return new URL(e).hostname}catch{return}};e.buildWebsiteExtractorUrl=a,e.fetchWebsiteExtractor=l,e.useBoolean=function(e=!1){const[n,r]=t.useState(e),u=t.useCallback(()=>r(!0),[]),o=t.useCallback(()=>r(!1),[]),i=t.useCallback(()=>r(e=>!e),[]);return{value:n,setValue:r,setTrue:u,setFalse:o,toggle:i}},e.useCopyToClipboard=function(e={}){const n=e.resetDelay??2e3,r=t.useRef(null),[u,o]=t.useState(null),i=t.useMemo(()=>!("undefined"==typeof navigator||!navigator.clipboard)||"undefined"!=typeof document&&("function"==typeof document.queryCommandSupported&&document.queryCommandSupported("copy")),[]),s=t.useCallback(()=>{r.current&&clearTimeout(r.current),r.current=setTimeout(()=>{o(null)},n)},[n]),c=t.useCallback(async e=>{if(!i)return!1;const t="undefined"!=typeof navigator&&!!navigator.clipboard;try{if(t)await navigator.clipboard.writeText(e);else if("undefined"!=typeof document){const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.focus(),t.select();const n=document.execCommand("copy");if(document.body.removeChild(t),!n)return!1}return o(e),s(),!0}catch{return!1}},[i,s]);return t.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]),{copy:c,copiedText:u,isSupported:i}},e.useDebounceCallback=r,e.useDebounceValue=u,e.useEventListener=o,e.useHover=function(e){const[n,r]=t.useState(!1),u=t.useCallback(()=>{r(!0)},[]),i=t.useCallback(()=>{r(!1)},[]);return o("pointerenter",u,e),o("pointerleave",i,e),n},e.useIsClient=i,e.useIsomorphicLayoutEffect=n,e.useLocalStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:o=JSON.stringify,deserialize:i=JSON.parse,listenToStorageChanges:s=!0}=r,c=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return c.current;if(!u)return c.current;try{const t=window.localStorage.getItem(e);return t?i(t):c.current}catch{return c.current}},[i,u,e]),[l,d]=t.useState(()=>a()),f=t.useCallback(t=>{d(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.localStorage.setItem(e,o(r))}catch{}return r})},[e,o]);return t.useEffect(()=>{d(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{d(i(t.newValue))}catch{d(c.current)}else d(c.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[i,e,s]),[l,f]},e.useMap=s,e.useMediaQuery=function(e,n={}){const[r,u]=t.useState(()=>"undefined"==typeof window||"function"!=typeof window.matchMedia?n.defaultValue??!1:window.matchMedia(e).matches);return t.useEffect(()=>{if("undefined"==typeof window||"function"!=typeof window.matchMedia)return;const t=window.matchMedia(e),n=e=>{u(e.matches)};return u(t.matches),t.addEventListener?(t.addEventListener("change",n),()=>t.removeEventListener("change",n)):(t.addListener(n),()=>t.removeListener(n))},[e]),r},e.useOnClickOutside=function(e,n,r="mousedown",u){const o=t.useRef(n);t.useEffect(()=>{o.current=n},[n]),t.useEffect(()=>{if("undefined"==typeof document)return;const t=Array.isArray(e)?e:[e],n=e=>{const n=e.target;if("undefined"==typeof Node||!(n instanceof Node))return;t.some(e=>{const t=e.current;return!!t&&t.contains(n)})||o.current(e)};return document.addEventListener(r,n,u),()=>{document.removeEventListener(r,n,u)}},[r,u,e])},e.useOpenGraphExtractor=function(e){const n=t.useMemo(()=>e.skipPatterns??f,[e.skipPatterns]),r=t.useCallback(e=>n.some(t=>t.test(e)),[n]),u=t.useCallback((e,t,n)=>{var r,u,o;const{openGraph:i,htmlInferred:s,hybridGraph:c}=e,a=p(null==i?void 0:i.description,null==c?void 0:c.description,null==s?void 0:s.description),l=p(null==i?void 0:i.title,null==c?void 0:c.title,null==s?void 0:s.title),d=p(null==i?void 0:i.site_name,null==c?void 0:c.site_name,null==s?void 0:s.site_name),f=p(null==c?void 0:c.favicon,null==s?void 0:s.favicon),v=p((null==(r=null==i?void 0:i.image)?void 0:r.url)??void 0,(null==c?void 0:c.image)??void 0,(null==s?void 0:s.image)??void 0,null==(u=null==s?void 0:s.images)?void 0:u[0]),y=p((null==(o=null==i?void 0:i.video)?void 0:o.url)??void 0,(null==c?void 0:c.video)??void 0),g=p(null==c?void 0:c.videoType,null==s?void 0:s.videoType),b=p(n.url,(null==i?void 0:i.url)??void 0,(null==c?void 0:c.url)??void 0,(null==s?void 0:s.url)??void 0,n.finalUrl,n.normalizedUrl,n.requestedUrl)??"";return{description:a,favicon:f,image:v,video:y,videoType:g,siteName:d,title:l,url:b,siteHost:m(b)}},[]);return d({endpoint:"open-graph",options:e,selectData:u,shouldSkip:r})},e.usePrevious=function(e){const n=t.useRef();return t.useEffect(()=>{n.current=e},[e]),n.current},e.useResizeObserver=function(e,r,u){const o=t.useRef(r),i=t.useRef(null),[s,c]=t.useState(null);return n(()=>{o.current=r},[r]),t.useEffect(()=>{if("undefined"==typeof ResizeObserver)return;const t="undefined"!=typeof Element&&e instanceof Element?e:(n=e)&&"object"==typeof n&&"current"in n?e.current:null;var n;if(!t)return;const r=new ResizeObserver(e=>{const t=e[0];i.current=t,o.current?o.current(t):c(t)});return r.observe(t,u),()=>r.disconnect()},[u,e]),o.current?i.current:s},e.useSessionStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:o=JSON.stringify,deserialize:i=JSON.parse,listenToStorageChanges:s=!1}=r,c=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return c.current;if(!u)return c.current;try{const t=window.sessionStorage.getItem(e);return t?i(t):c.current}catch{return c.current}},[i,u,e]),[l,d]=t.useState(()=>a()),f=t.useCallback(t=>{d(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.sessionStorage.setItem(e,o(r))}catch{}return r})},[e,o]);return t.useEffect(()=>{d(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{d(i(t.newValue))}catch{d(c.current)}else d(c.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[i,e,s]),[l,f]},e.useThrottle=function(e,n,r={}){const u=r.leading??!0,o=r.trailing??!0,i=Math.max(0,n),[s,c]=t.useState(e),a=t.useRef(0),l=t.useRef(null),d=t.useRef(null);return t.useEffect(()=>{if(0===i)return void c(e);const t=Date.now();if(0===a.current)return a.current=t,u?void c(e):void(o&&!l.current&&(d.current=e,l.current=setTimeout(()=>{l.current=null,null!==d.current&&(c(d.current),d.current=null,a.current=Date.now())},i)));const n=t-a.current;if(n>=i&&u)return c(e),a.current=t,void(d.current=null);if(o&&(d.current=e,!l.current)){const e=Math.max(i-n,0);l.current=setTimeout(()=>{l.current=null,null!==d.current&&(c(d.current),d.current=null,a.current=Date.now())},e)}},[u,o,e,i]),t.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]),s},e.useWebsiteLinksExtractor=function(e){return d({endpoint:"links",options:e,selectData:t.useCallback(e=>({totalLinks:e.totalLinks??0,uniqueDomains:e.uniqueDomains??0,links:e.links??[]}),[])})},e.useWebsiteMetaExtractor=function(e){return d({endpoint:"meta",options:e,selectData:t.useCallback(e=>({title:e.title??void 0,description:e.description??void 0,language:e.language??void 0,canonicalUrl:e.canonicalUrl??void 0,feedUrl:e.feedUrl??null,textContentLength:e.textContentLength??void 0,metaTags:e.metaTags??{}}),[])})},e.useWebsiteRssExtractor=function(e){return d({endpoint:"rss",options:e,selectData:t.useCallback(e=>({feedUrl:e.feedUrl??null,feeds:e.feeds??[]}),[])})},e.useWebsiteSchemaExtractor=function(e){return d({endpoint:"schema",options:e,selectData:t.useCallback(e=>({schema:e.schema??[],schemaTypes:e.schemaTypes??[]}),[])})},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
2
2
  //# sourceMappingURL=opensite-hooks.umd.js.map
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).OpensiteHooks={},e.React)}(this,function(e,t){"use strict";const n="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;function r(e,r,u={}){const c=t.useRef(e),o=t.useRef(null),s=t.useRef(null),i=t.useRef(null),a=u.leading??!1,l=u.trailing??!0,f=u.maxWait,d=Math.max(0,r);n(()=>{c.current=e},[e]);const p=t.useCallback(()=>{o.current&&(clearTimeout(o.current),o.current=null),s.current&&(clearTimeout(s.current),s.current=null)},[]),m=t.useCallback(()=>{if(!i.current)return;const e=i.current;i.current=null,c.current(...e)},[]),y=t.useCallback((...e)=>{i.current=e;if(a&&null===o.current&&null===s.current&&m(),o.current&&clearTimeout(o.current),l&&(o.current=setTimeout(()=>{o.current=null,i.current&&m(),s.current&&(clearTimeout(s.current),s.current=null)},d)),null!=f&&l&&!s.current){const e=Math.max(0,f);s.current=setTimeout(()=>{s.current=null,o.current&&(clearTimeout(o.current),o.current=null),i.current&&m()},e)}},[m,a,l,f,d]),w=t.useCallback(()=>{p(),i.current=null},[p]),v=t.useCallback(()=>{i.current&&(p(),m())},[p,m]);return t.useEffect(()=>()=>w(),[w]),{debouncedCallback:y,cancel:w,flush:v}}function u(e,r,u,c){const o=t.useRef(r);n(()=>{o.current=r},[r]),t.useEffect(()=>{const t="undefined"!=typeof Window&&u instanceof Window,n="undefined"!=typeof Document&&u instanceof Document,r=void 0===u?"undefined"!=typeof window?window:null:t||n||"undefined"!=typeof HTMLElement&&u instanceof HTMLElement?u:(s=u)&&"object"==typeof s&&"current"in s?u.current:null;var s;if(!(null==r?void 0:r.addEventListener))return;const i=e=>{const t=o.current;"function"==typeof t?t(e):t.handleEvent(e)};return r.addEventListener(e,i,c),()=>{r.removeEventListener(e,i,c)}},[e,u,c])}e.useBoolean=function(e=!1){const[n,r]=t.useState(e),u=t.useCallback(()=>r(!0),[]),c=t.useCallback(()=>r(!1),[]),o=t.useCallback(()=>r(e=>!e),[]);return{value:n,setValue:r,setTrue:u,setFalse:c,toggle:o}},e.useCopyToClipboard=function(e={}){const n=e.resetDelay??2e3,r=t.useRef(null),[u,c]=t.useState(null),o=t.useMemo(()=>!("undefined"==typeof navigator||!navigator.clipboard)||"undefined"!=typeof document&&("function"==typeof document.queryCommandSupported&&document.queryCommandSupported("copy")),[]),s=t.useCallback(()=>{r.current&&clearTimeout(r.current),r.current=setTimeout(()=>{c(null)},n)},[n]),i=t.useCallback(async e=>{if(!o)return!1;const t="undefined"!=typeof navigator&&!!navigator.clipboard;try{if(t)await navigator.clipboard.writeText(e);else if("undefined"!=typeof document){const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.focus(),t.select();const n=document.execCommand("copy");if(document.body.removeChild(t),!n)return!1}return c(e),s(),!0}catch{return!1}},[o,s]);return t.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]),{copy:i,copiedText:u,isSupported:o}},e.useDebounceCallback=r,e.useDebounceValue=function(e,n,u){const[c,o]=t.useState(e),{debouncedCallback:s,cancel:i}=r(e=>{o(e)},n,u);return t.useEffect(()=>{s(e)},[s,e]),t.useEffect(()=>()=>i(),[i]),c},e.useEventListener=u,e.useHover=function(e){const[n,r]=t.useState(!1),c=t.useCallback(()=>{r(!0)},[]),o=t.useCallback(()=>{r(!1)},[]);return u("pointerenter",c,e),u("pointerleave",o,e),n},e.useIsClient=function(){const[e,n]=t.useState(!1);return t.useEffect(()=>{n(!0)},[]),e},e.useIsomorphicLayoutEffect=n,e.useLocalStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:c=JSON.stringify,deserialize:o=JSON.parse,listenToStorageChanges:s=!0}=r,i=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return i.current;if(!u)return i.current;try{const t=window.localStorage.getItem(e);return t?o(t):i.current}catch{return i.current}},[o,u,e]),[l,f]=t.useState(()=>a()),d=t.useCallback(t=>{f(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.localStorage.setItem(e,c(r))}catch{}return r})},[e,c]);return t.useEffect(()=>{f(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{f(o(t.newValue))}catch{f(i.current)}else f(i.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[o,e,s]),[l,d]},e.useMap=function(e){const[n,r]=t.useState(()=>e instanceof Map||Array.isArray(e)?new Map(e):new Map),u=t.useRef(n);t.useEffect(()=>{u.current=n},[n]);const c=t.useMemo(()=>({set:(e,t)=>{r(n=>{const r=new Map(n);return r.set(e,t),r})},setAll:e=>{r((Map,new Map(e)))},remove:e=>{r(t=>{const n=new Map(t);return n.delete(e),n})},clear:()=>r(new Map),get:e=>u.current.get(e),has:e=>u.current.has(e)}),[]);return[n,c]},e.useMediaQuery=function(e,n={}){const[r,u]=t.useState(()=>"undefined"==typeof window||"function"!=typeof window.matchMedia?n.defaultValue??!1:window.matchMedia(e).matches);return t.useEffect(()=>{if("undefined"==typeof window||"function"!=typeof window.matchMedia)return;const t=window.matchMedia(e),n=e=>{u(e.matches)};return u(t.matches),t.addEventListener?(t.addEventListener("change",n),()=>t.removeEventListener("change",n)):(t.addListener(n),()=>t.removeListener(n))},[e]),r},e.useOnClickOutside=function(e,n,r="mousedown",u){const c=t.useRef(n);t.useEffect(()=>{c.current=n},[n]),t.useEffect(()=>{if("undefined"==typeof document)return;const t=Array.isArray(e)?e:[e],n=e=>{const n=e.target;if("undefined"==typeof Node||!(n instanceof Node))return;t.some(e=>{const t=e.current;return!!t&&t.contains(n)})||c.current(e)};return document.addEventListener(r,n,u),()=>{document.removeEventListener(r,n,u)}},[r,u,e])},e.usePrevious=function(e){const n=t.useRef();return t.useEffect(()=>{n.current=e},[e]),n.current},e.useResizeObserver=function(e,r,u){const c=t.useRef(r),o=t.useRef(null),[s,i]=t.useState(null);return n(()=>{c.current=r},[r]),t.useEffect(()=>{if("undefined"==typeof ResizeObserver)return;const t="undefined"!=typeof Element&&e instanceof Element?e:(n=e)&&"object"==typeof n&&"current"in n?e.current:null;var n;if(!t)return;const r=new ResizeObserver(e=>{const t=e[0];o.current=t,c.current?c.current(t):i(t)});return r.observe(t,u),()=>r.disconnect()},[u,e]),c.current?o.current:s},e.useSessionStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:c=JSON.stringify,deserialize:o=JSON.parse,listenToStorageChanges:s=!1}=r,i=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return i.current;if(!u)return i.current;try{const t=window.sessionStorage.getItem(e);return t?o(t):i.current}catch{return i.current}},[o,u,e]),[l,f]=t.useState(()=>a()),d=t.useCallback(t=>{f(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.sessionStorage.setItem(e,c(r))}catch{}return r})},[e,c]);return t.useEffect(()=>{f(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{f(o(t.newValue))}catch{f(i.current)}else f(i.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[o,e,s]),[l,d]},e.useThrottle=function(e,n,r={}){const u=r.leading??!0,c=r.trailing??!0,o=Math.max(0,n),[s,i]=t.useState(e),a=t.useRef(0),l=t.useRef(null),f=t.useRef(null);return t.useEffect(()=>{if(0===o)return void i(e);const t=Date.now();if(0===a.current)return a.current=t,u?void i(e):void(c&&!l.current&&(f.current=e,l.current=setTimeout(()=>{l.current=null,null!==f.current&&(i(f.current),f.current=null,a.current=Date.now())},o)));const n=t-a.current;if(n>=o&&u)return i(e),a.current=t,void(f.current=null);if(c&&(f.current=e,!l.current)){const e=Math.max(o-n,0);l.current=setTimeout(()=>{l.current=null,null!==f.current&&(i(f.current),f.current=null,a.current=Date.now())},e)}},[u,c,e,o]),t.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]),s},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).OpensiteHooks={},e.React)}(this,function(e,t){"use strict";const n="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;function r(e,r,u={}){const o=t.useRef(e),i=t.useRef(null),s=t.useRef(null),c=t.useRef(null),a=u.leading??!1,l=u.trailing??!0,d=u.maxWait,f=Math.max(0,r);n(()=>{o.current=e},[e]);const p=t.useCallback(()=>{i.current&&(clearTimeout(i.current),i.current=null),s.current&&(clearTimeout(s.current),s.current=null)},[]),m=t.useCallback(()=>{if(!c.current)return;const e=c.current;c.current=null,o.current(...e)},[]),v=t.useCallback((...e)=>{c.current=e;if(a&&null===i.current&&null===s.current&&m(),i.current&&clearTimeout(i.current),l&&(i.current=setTimeout(()=>{i.current=null,c.current&&m(),s.current&&(clearTimeout(s.current),s.current=null)},f)),null!=d&&l&&!s.current){const e=Math.max(0,d);s.current=setTimeout(()=>{s.current=null,i.current&&(clearTimeout(i.current),i.current=null),c.current&&m()},e)}},[m,a,l,d,f]),y=t.useCallback(()=>{p(),c.current=null},[p]),g=t.useCallback(()=>{c.current&&(p(),m())},[p,m]);return t.useEffect(()=>()=>y(),[y]),{debouncedCallback:v,cancel:y,flush:g}}function u(e,n,u){const[o,i]=t.useState(e),{debouncedCallback:s,cancel:c}=r(e=>{i(e)},n,u);return t.useEffect(()=>{s(e)},[s,e]),t.useEffect(()=>()=>c(),[c]),o}function o(e,r,u,o){const i=t.useRef(r);n(()=>{i.current=r},[r]),t.useEffect(()=>{const t="undefined"!=typeof Window&&u instanceof Window,n="undefined"!=typeof Document&&u instanceof Document,r=void 0===u?"undefined"!=typeof window?window:null:t||n||"undefined"!=typeof HTMLElement&&u instanceof HTMLElement?u:(s=u)&&"object"==typeof s&&"current"in s?u.current:null;var s;if(!(null==r?void 0:r.addEventListener))return;const c=e=>{const t=i.current;"function"==typeof t?t(e):t.handleEvent(e)};return r.addEventListener(e,c,o),()=>{r.removeEventListener(e,c,o)}},[e,u,o])}function i(){const[e,n]=t.useState(!1);return t.useEffect(()=>{n(!0)},[]),e}function s(e){const[n,r]=t.useState(()=>e instanceof Map||Array.isArray(e)?new Map(e):new Map),u=t.useRef(n);t.useEffect(()=>{u.current=n},[n]);const o=t.useMemo(()=>({set:(e,t)=>{r(n=>{const r=new Map(n);return r.set(e,t),r})},setAll:e=>{r((Map,new Map(e)))},remove:e=>{r(t=>{const n=new Map(t);return n.delete(e),n})},clear:()=>r(new Map),get:e=>u.current.get(e),has:e=>u.current.has(e)}),[]);return[n,o]}const c="https://octane.buzz";function a(e){const t=function(e){return e.replace(/\/+$/,"")}(e.baseUrl??c),n=new URLSearchParams;return e.apiKey&&n.set("api_key",e.apiKey),n.set("url",e.url),`${t}/api/v1/extract/${e.endpoint}?${n.toString()}`}async function l(e){var t;if(!e.url||0===e.url.trim().length)return{ok:!1,error:{message:"URL is required."}};const n=a(e);try{const t=await fetch(n,{method:"GET",signal:e.signal});let r=null;try{r=await t.json()}catch{r=null}if(!t.ok){const e=r;return{ok:!1,error:{message:(null==e?void 0:e.error)??`Request failed with status ${t.status}.`,status:(null==e?void 0:e.status)??t.status,raw:r}}}return{ok:!0,response:r}}catch(r){return(null==(t=e.signal)?void 0:t.aborted)?{ok:!1,error:{message:"Request aborted."}}:{ok:!1,error:{message:r instanceof Error?r.message:"Request failed unexpectedly.",raw:r}}}}function d(e){const{endpoint:n,options:o,selectData:a,shouldSkip:d}=e,f=i(),[p,m]=t.useState({loading:!1}),[,v]=s(),y=o.cache??true,g=o.enabled??true,b=o.debounceMs??250,w=o.refreshDebounceMs??150,h=u(t.useMemo(()=>{var e;return(null==(e=o.url)?void 0:e.trim())??""},[o.url]),b),E=t.useRef(0),k=t.useRef(0),[C,T]=t.useState(0),{debouncedCallback:S,cancel:R}=r(()=>{E.current+=1,T(E.current)},w),M=t.useCallback(()=>{S()},[S]);t.useEffect(()=>()=>R(),[R]);const x=t.useMemo(()=>{if(!h)return"";const e=o.baseUrl??c,t=o.apiKey??"";return`${n}:${e}:${t}:${h}`},[n,o.apiKey,o.baseUrl,h]),L=t.useRef(null);return t.useEffect(()=>{var e;if(!f)return;if(!g||!h)return void m({loading:!1});if(null==d?void 0:d(h))return void m({loading:!1});const t=C!==k.current;if(t&&(k.current=C),y&&!t){const e=v.get(x);if(e)return void m({loading:!1,data:e.data,raw:e.raw,meta:e.meta})}null==(e=L.current)||e.abort();const r=new AbortController;return L.current=r,m(e=>({...e,loading:!0,error:void 0})),l({endpoint:n,url:h,apiKey:o.apiKey,baseUrl:o.baseUrl,signal:r.signal}).then(e=>{if(r.signal.aborted)return;if(!e.ok)return void m(t=>({...t,loading:!1,error:e.error}));const t=e.response,n=function(e){const{requestedUrl:t,finalUrl:n,url:r,normalizedUrl:u,status:o,contentType:i,fetchedAt:s,bodyBytes:c,bodyTruncated:a,maxBodyBytes:l,cache:d}=e;return{requestedUrl:t,finalUrl:n,url:r,normalizedUrl:u,status:o,contentType:i,fetchedAt:s,bodyBytes:c,bodyTruncated:a,maxBodyBytes:l,cache:d}}(t),u=function(e){const{requestedUrl:t,finalUrl:n,url:r,normalizedUrl:u,status:o,contentType:i,fetchedAt:s,bodyBytes:c,bodyTruncated:a,maxBodyBytes:l,cache:d,...f}=e;return f}(t),o=a(u,t,n);y&&v.set(x,{data:o,raw:t,meta:n}),m({loading:!1,data:o,raw:t,meta:n})}).catch(e=>{r.signal.aborted||m(t=>({...t,loading:!1,error:{message:e instanceof Error?e.message:"Request failed unexpectedly.",raw:e}}))}),()=>{r.abort()}},[v,y,h,g,n,f,o.apiKey,o.baseUrl,x,C,a,d]),t.useMemo(()=>({...p,refresh:M}),[M,p])}const f=[/search\.google\.com\/local\/reviews/i,/google\.com\/maps\/place/i,/maps\.google\.com/i,/opentable\.com/i],p=(...e)=>{for(const t of e)if("string"==typeof t&&t.trim().length>0)return t},m=e=>{if(e)try{return new URL(e).hostname}catch{return}};e.buildWebsiteExtractorUrl=a,e.fetchWebsiteExtractor=l,e.useBoolean=function(e=!1){const[n,r]=t.useState(e),u=t.useCallback(()=>r(!0),[]),o=t.useCallback(()=>r(!1),[]),i=t.useCallback(()=>r(e=>!e),[]);return{value:n,setValue:r,setTrue:u,setFalse:o,toggle:i}},e.useCopyToClipboard=function(e={}){const n=e.resetDelay??2e3,r=t.useRef(null),[u,o]=t.useState(null),i=t.useMemo(()=>!("undefined"==typeof navigator||!navigator.clipboard)||"undefined"!=typeof document&&("function"==typeof document.queryCommandSupported&&document.queryCommandSupported("copy")),[]),s=t.useCallback(()=>{r.current&&clearTimeout(r.current),r.current=setTimeout(()=>{o(null)},n)},[n]),c=t.useCallback(async e=>{if(!i)return!1;const t="undefined"!=typeof navigator&&!!navigator.clipboard;try{if(t)await navigator.clipboard.writeText(e);else if("undefined"!=typeof document){const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.focus(),t.select();const n=document.execCommand("copy");if(document.body.removeChild(t),!n)return!1}return o(e),s(),!0}catch{return!1}},[i,s]);return t.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]),{copy:c,copiedText:u,isSupported:i}},e.useDebounceCallback=r,e.useDebounceValue=u,e.useEventListener=o,e.useHover=function(e){const[n,r]=t.useState(!1),u=t.useCallback(()=>{r(!0)},[]),i=t.useCallback(()=>{r(!1)},[]);return o("pointerenter",u,e),o("pointerleave",i,e),n},e.useIsClient=i,e.useIsomorphicLayoutEffect=n,e.useLocalStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:o=JSON.stringify,deserialize:i=JSON.parse,listenToStorageChanges:s=!0}=r,c=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return c.current;if(!u)return c.current;try{const t=window.localStorage.getItem(e);return t?i(t):c.current}catch{return c.current}},[i,u,e]),[l,d]=t.useState(()=>a()),f=t.useCallback(t=>{d(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.localStorage.setItem(e,o(r))}catch{}return r})},[e,o]);return t.useEffect(()=>{d(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{d(i(t.newValue))}catch{d(c.current)}else d(c.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[i,e,s]),[l,f]},e.useMap=s,e.useMediaQuery=function(e,n={}){const[r,u]=t.useState(()=>"undefined"==typeof window||"function"!=typeof window.matchMedia?n.defaultValue??!1:window.matchMedia(e).matches);return t.useEffect(()=>{if("undefined"==typeof window||"function"!=typeof window.matchMedia)return;const t=window.matchMedia(e),n=e=>{u(e.matches)};return u(t.matches),t.addEventListener?(t.addEventListener("change",n),()=>t.removeEventListener("change",n)):(t.addListener(n),()=>t.removeListener(n))},[e]),r},e.useOnClickOutside=function(e,n,r="mousedown",u){const o=t.useRef(n);t.useEffect(()=>{o.current=n},[n]),t.useEffect(()=>{if("undefined"==typeof document)return;const t=Array.isArray(e)?e:[e],n=e=>{const n=e.target;if("undefined"==typeof Node||!(n instanceof Node))return;t.some(e=>{const t=e.current;return!!t&&t.contains(n)})||o.current(e)};return document.addEventListener(r,n,u),()=>{document.removeEventListener(r,n,u)}},[r,u,e])},e.useOpenGraphExtractor=function(e){const n=t.useMemo(()=>e.skipPatterns??f,[e.skipPatterns]),r=t.useCallback(e=>n.some(t=>t.test(e)),[n]),u=t.useCallback((e,t,n)=>{var r,u,o;const{openGraph:i,htmlInferred:s,hybridGraph:c}=e,a=p(null==i?void 0:i.description,null==c?void 0:c.description,null==s?void 0:s.description),l=p(null==i?void 0:i.title,null==c?void 0:c.title,null==s?void 0:s.title),d=p(null==i?void 0:i.site_name,null==c?void 0:c.site_name,null==s?void 0:s.site_name),f=p(null==c?void 0:c.favicon,null==s?void 0:s.favicon),v=p((null==(r=null==i?void 0:i.image)?void 0:r.url)??void 0,(null==c?void 0:c.image)??void 0,(null==s?void 0:s.image)??void 0,null==(u=null==s?void 0:s.images)?void 0:u[0]),y=p((null==(o=null==i?void 0:i.video)?void 0:o.url)??void 0,(null==c?void 0:c.video)??void 0),g=p(null==c?void 0:c.videoType,null==s?void 0:s.videoType),b=p(n.url,(null==i?void 0:i.url)??void 0,(null==c?void 0:c.url)??void 0,(null==s?void 0:s.url)??void 0,n.finalUrl,n.normalizedUrl,n.requestedUrl)??"";return{description:a,favicon:f,image:v,video:y,videoType:g,siteName:d,title:l,url:b,siteHost:m(b)}},[]);return d({endpoint:"open-graph",options:e,selectData:u,shouldSkip:r})},e.usePrevious=function(e){const n=t.useRef();return t.useEffect(()=>{n.current=e},[e]),n.current},e.useResizeObserver=function(e,r,u){const o=t.useRef(r),i=t.useRef(null),[s,c]=t.useState(null);return n(()=>{o.current=r},[r]),t.useEffect(()=>{if("undefined"==typeof ResizeObserver)return;const t="undefined"!=typeof Element&&e instanceof Element?e:(n=e)&&"object"==typeof n&&"current"in n?e.current:null;var n;if(!t)return;const r=new ResizeObserver(e=>{const t=e[0];i.current=t,o.current?o.current(t):c(t)});return r.observe(t,u),()=>r.disconnect()},[u,e]),o.current?i.current:s},e.useSessionStorage=function(e,n,r={}){const{initializeWithValue:u=!0,serialize:o=JSON.stringify,deserialize:i=JSON.parse,listenToStorageChanges:s=!1}=r,c=t.useRef(n),a=t.useCallback(()=>{if("undefined"==typeof window)return c.current;if(!u)return c.current;try{const t=window.sessionStorage.getItem(e);return t?i(t):c.current}catch{return c.current}},[i,u,e]),[l,d]=t.useState(()=>a()),f=t.useCallback(t=>{d(n=>{const r="function"==typeof t?t(n):t;if("undefined"!=typeof window)try{window.sessionStorage.setItem(e,o(r))}catch{}return r})},[e,o]);return t.useEffect(()=>{d(a())},[a]),t.useEffect(()=>{if("undefined"==typeof window||!s)return;const t=t=>{if(t.key===e)if(null!==t.newValue)try{d(i(t.newValue))}catch{d(c.current)}else d(c.current)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[i,e,s]),[l,f]},e.useThrottle=function(e,n,r={}){const u=r.leading??!0,o=r.trailing??!0,i=Math.max(0,n),[s,c]=t.useState(e),a=t.useRef(0),l=t.useRef(null),d=t.useRef(null);return t.useEffect(()=>{if(0===i)return void c(e);const t=Date.now();if(0===a.current)return a.current=t,u?void c(e):void(o&&!l.current&&(d.current=e,l.current=setTimeout(()=>{l.current=null,null!==d.current&&(c(d.current),d.current=null,a.current=Date.now())},i)));const n=t-a.current;if(n>=i&&u)return c(e),a.current=t,void(d.current=null);if(o&&(d.current=e,!l.current)){const e=Math.max(i-n,0);l.current=setTimeout(()=>{l.current=null,null!==d.current&&(c(d.current),d.current=null,a.current=Date.now())},e)}},[u,o,e,i]),t.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]),s},e.useWebsiteLinksExtractor=function(e){return d({endpoint:"links",options:e,selectData:t.useCallback(e=>({totalLinks:e.totalLinks??0,uniqueDomains:e.uniqueDomains??0,links:e.links??[]}),[])})},e.useWebsiteMetaExtractor=function(e){return d({endpoint:"meta",options:e,selectData:t.useCallback(e=>({title:e.title??void 0,description:e.description??void 0,language:e.language??void 0,canonicalUrl:e.canonicalUrl??void 0,feedUrl:e.feedUrl??null,textContentLength:e.textContentLength??void 0,metaTags:e.metaTags??{}}),[])})},e.useWebsiteRssExtractor=function(e){return d({endpoint:"rss",options:e,selectData:t.useCallback(e=>({feedUrl:e.feedUrl??null,feeds:e.feeds??[]}),[])})},e.useWebsiteSchemaExtractor=function(e){return d({endpoint:"schema",options:e,selectData:t.useCallback(e=>({schema:e.schema??[],schemaTypes:e.schemaTypes??[]}),[])})},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
2
2
  //# sourceMappingURL=opensite-hooks.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opensite-hooks.umd.js","sources":["../../src/core/useIsomorphicLayoutEffect.ts","../../src/core/useDebounceCallback.ts","../../src/core/useEventListener.ts","../../src/core/useBoolean.ts","../../src/core/useCopyToClipboard.ts","../../src/core/useDebounceValue.ts","../../src/core/useHover.ts","../../src/core/useIsClient.ts","../../src/core/useLocalStorage.ts","../../src/core/useMap.ts","../../src/core/useMediaQuery.ts","../../src/core/useOnClickOutside.ts","../../src/core/usePrevious.ts","../../src/core/useResizeObserver.ts","../../src/core/useSessionStorage.ts","../../src/core/useThrottle.ts"],"sourcesContent":["import { useEffect, useLayoutEffect } from \"react\";\n\nexport const useIsomorphicLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\nexport interface DebounceOptions {\n leading?: boolean;\n trailing?: boolean;\n maxWait?: number;\n}\n\nexport interface DebouncedCallback<T extends (...args: any[]) => void> {\n debouncedCallback: (...args: Parameters<T>) => void;\n cancel: () => void;\n flush: () => void;\n}\n\nexport function useDebounceCallback<T extends (...args: any[]) => void>(\n callback: T,\n delay: number,\n options: DebounceOptions = {}\n): DebouncedCallback<T> {\n const callbackRef = useRef(callback);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const maxTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastArgsRef = useRef<Parameters<T> | null>(null);\n\n const leading = options.leading ?? false;\n const trailing = options.trailing ?? true;\n const maxWait = options.maxWait;\n const wait = Math.max(0, delay);\n\n useIsomorphicLayoutEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const clearTimers = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (maxTimeoutRef.current) {\n clearTimeout(maxTimeoutRef.current);\n maxTimeoutRef.current = null;\n }\n }, []);\n\n const invoke = useCallback(() => {\n if (!lastArgsRef.current) {\n return;\n }\n const args = lastArgsRef.current;\n lastArgsRef.current = null;\n callbackRef.current(...args);\n }, []);\n\n const debouncedCallback = useCallback(\n (...args: Parameters<T>) => {\n lastArgsRef.current = args;\n\n const shouldInvokeLeading =\n leading && timeoutRef.current === null && maxTimeoutRef.current === null;\n if (shouldInvokeLeading) {\n invoke();\n }\n\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n if (trailing) {\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n if (lastArgsRef.current) {\n invoke();\n }\n if (maxTimeoutRef.current) {\n clearTimeout(maxTimeoutRef.current);\n maxTimeoutRef.current = null;\n }\n }, wait);\n }\n\n if (maxWait !== undefined && maxWait !== null && trailing) {\n if (!maxTimeoutRef.current) {\n const maxDelay = Math.max(0, maxWait);\n maxTimeoutRef.current = setTimeout(() => {\n maxTimeoutRef.current = null;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (lastArgsRef.current) {\n invoke();\n }\n }, maxDelay);\n }\n }\n },\n [invoke, leading, trailing, maxWait, wait]\n );\n\n const cancel = useCallback(() => {\n clearTimers();\n lastArgsRef.current = null;\n }, [clearTimers]);\n\n const flush = useCallback(() => {\n if (!lastArgsRef.current) {\n return;\n }\n clearTimers();\n invoke();\n }, [clearTimers, invoke]);\n\n useEffect(() => () => cancel(), [cancel]);\n\n return { debouncedCallback, cancel, flush };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\ntype EventTargetLike = Window | Document | HTMLElement | null;\ntype ElementRef = React.RefObject<HTMLElement>;\n\nconst isRefObject = (value: unknown): value is ElementRef =>\n !!value && typeof value === \"object\" && \"current\" in value;\n\nexport function useEventListener<K extends keyof WindowEventMap>(\n eventName: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: Window,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener<K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: Document,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener<K extends keyof HTMLElementEventMap>(\n eventName: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: ElementRef,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener<K extends keyof HTMLElementEventMap>(\n eventName: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: HTMLElement,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener(\n eventName: string,\n handler: EventListenerOrEventListenerObject,\n element?: EventTargetLike | ElementRef,\n options?: AddEventListenerOptions | boolean\n): void {\n const savedHandler = useRef(handler);\n\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const isWindow =\n typeof Window !== \"undefined\" && element instanceof Window;\n const isDocument =\n typeof Document !== \"undefined\" && element instanceof Document;\n\n const target: EventTargetLike | null =\n element === undefined\n ? typeof window !== \"undefined\"\n ? window\n : null\n : isWindow || isDocument\n ? element\n : typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement\n ? element\n : isRefObject(element)\n ? element.current\n : null;\n\n if (!target?.addEventListener) {\n return;\n }\n\n const listener = (event: Event) => {\n const currentHandler = savedHandler.current;\n if (typeof currentHandler === \"function\") {\n currentHandler(event);\n } else {\n currentHandler.handleEvent(event);\n }\n };\n\n target.addEventListener(eventName, listener, options);\n\n return () => {\n target.removeEventListener(eventName, listener, options);\n };\n }, [eventName, element, options]);\n}\n","import { useCallback, useState } from \"react\";\n\nexport interface UseBooleanResult {\n value: boolean;\n setValue: React.Dispatch<React.SetStateAction<boolean>>;\n setTrue: () => void;\n setFalse: () => void;\n toggle: () => void;\n}\n\nexport function useBoolean(defaultValue = false): UseBooleanResult {\n const [value, setValue] = useState<boolean>(defaultValue);\n\n const setTrue = useCallback(() => setValue(true), []);\n const setFalse = useCallback(() => setValue(false), []);\n const toggle = useCallback(() => setValue((current) => !current), []);\n\n return { value, setValue, setTrue, setFalse, toggle };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface UseCopyToClipboardOptions {\n resetDelay?: number;\n}\n\nexport interface CopyToClipboardResult {\n copy: (text: string) => Promise<boolean>;\n copiedText: string | null;\n isSupported: boolean;\n}\n\nexport function useCopyToClipboard(\n options: UseCopyToClipboardOptions = {}\n): CopyToClipboardResult {\n const resetDelay = options.resetDelay ?? 2000;\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [copiedText, setCopiedText] = useState<string | null>(null);\n\n const isSupported = useMemo(() => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n return true;\n }\n if (typeof document === \"undefined\") {\n return false;\n }\n if (typeof document.queryCommandSupported !== \"function\") {\n return false;\n }\n return document.queryCommandSupported(\"copy\");\n }, []);\n\n const resetCopied = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n setCopiedText(null);\n }, resetDelay);\n }, [resetDelay]);\n\n const copy = useCallback(\n async (text: string) => {\n if (!isSupported) {\n return false;\n }\n\n const shouldUseClipboardApi =\n typeof navigator !== \"undefined\" && !!navigator.clipboard;\n\n try {\n if (shouldUseClipboardApi) {\n await navigator.clipboard.writeText(text);\n } else if (typeof document !== \"undefined\") {\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"fixed\";\n textarea.style.left = \"-9999px\";\n textarea.style.top = \"0\";\n document.body.appendChild(textarea);\n textarea.focus();\n textarea.select();\n const success = document.execCommand(\"copy\");\n document.body.removeChild(textarea);\n if (!success) {\n return false;\n }\n }\n\n setCopiedText(text);\n resetCopied();\n return true;\n } catch {\n return false;\n }\n },\n [isSupported, resetCopied]\n );\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return { copy, copiedText, isSupported };\n}\n","import { useEffect, useState } from \"react\";\nimport { DebounceOptions, useDebounceCallback } from \"./useDebounceCallback.js\";\n\nexport function useDebounceValue<T>(\n value: T,\n delay: number,\n options?: DebounceOptions\n): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n const { debouncedCallback, cancel } = useDebounceCallback(\n (next: T) => {\n setDebouncedValue(next);\n },\n delay,\n options\n );\n\n useEffect(() => {\n debouncedCallback(value);\n }, [debouncedCallback, value]);\n\n useEffect(() => () => cancel(), [cancel]);\n\n return debouncedValue;\n}\n","import { useCallback, useState } from \"react\";\nimport { useEventListener } from \"./useEventListener.js\";\n\nexport function useHover<T extends HTMLElement>(\n ref: React.RefObject<T>\n): boolean {\n const [isHovered, setIsHovered] = useState(false);\n\n const handleEnter = useCallback(() => {\n setIsHovered(true);\n }, []);\n\n const handleLeave = useCallback(() => {\n setIsHovered(false);\n }, []);\n\n useEventListener(\"pointerenter\", handleEnter, ref);\n useEventListener(\"pointerleave\", handleLeave, ref);\n\n return isHovered;\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useIsClient(): boolean {\n const [isClient, setIsClient] = useState(false);\n\n useEffect(() => {\n setIsClient(true);\n }, []);\n\n return isClient;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface StorageOptions<T> {\n initializeWithValue?: boolean;\n serialize?: (value: T) => string;\n deserialize?: (value: string) => T;\n listenToStorageChanges?: boolean;\n}\n\ntype StoredSetter<T> = (value: T | ((current: T) => T)) => void;\n\nexport function useLocalStorage<T>(\n key: string,\n initialValue: T,\n options: StorageOptions<T> = {}\n): [T, StoredSetter<T>] {\n const {\n initializeWithValue = true,\n serialize = JSON.stringify,\n deserialize = JSON.parse as (value: string) => T,\n listenToStorageChanges = true,\n } = options;\n\n const initialValueRef = useRef(initialValue);\n\n const readValue = useCallback(() => {\n if (typeof window === \"undefined\") {\n return initialValueRef.current;\n }\n if (!initializeWithValue) {\n return initialValueRef.current;\n }\n try {\n const item = window.localStorage.getItem(key);\n return item ? deserialize(item) : initialValueRef.current;\n } catch {\n return initialValueRef.current;\n }\n }, [deserialize, initializeWithValue, key]);\n\n const [storedValue, setStoredValue] = useState<T>(() => readValue());\n\n const setValue: StoredSetter<T> = useCallback(\n (value) => {\n setStoredValue((current) => {\n const valueToStore =\n typeof value === \"function\"\n ? (value as (current: T) => T)(current)\n : value;\n if (typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(key, serialize(valueToStore));\n } catch {\n // Ignore write errors (quota/security)\n }\n }\n return valueToStore;\n });\n },\n [key, serialize]\n );\n\n useEffect(() => {\n setStoredValue(readValue());\n }, [readValue]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !listenToStorageChanges) {\n return;\n }\n\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key !== key) {\n return;\n }\n if (event.newValue === null) {\n setStoredValue(initialValueRef.current);\n return;\n }\n try {\n setStoredValue(deserialize(event.newValue));\n } catch {\n setStoredValue(initialValueRef.current);\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [deserialize, key, listenToStorageChanges]);\n\n return [storedValue, setValue];\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface MapActions<K, V> {\n set: (key: K, value: V) => void;\n setAll: (entries: Map<K, V> | [K, V][]) => void;\n remove: (key: K) => void;\n clear: () => void;\n get: (key: K) => V | undefined;\n has: (key: K) => boolean;\n}\n\nexport function useMap<K, V>(\n initialState?: Map<K, V> | [K, V][]\n): [Map<K, V>, MapActions<K, V>] {\n const [map, setMap] = useState<Map<K, V>>(() => {\n if (initialState instanceof Map) {\n return new Map(initialState);\n }\n if (Array.isArray(initialState)) {\n return new Map(initialState);\n }\n return new Map();\n });\n\n const mapRef = useRef(map);\n\n useEffect(() => {\n mapRef.current = map;\n }, [map]);\n\n const actions = useMemo<MapActions<K, V>>(\n () => ({\n set: (key: K, value: V) => {\n setMap((prev) => {\n const next = new Map(prev);\n next.set(key, value);\n return next;\n });\n },\n setAll: (entries: Map<K, V> | [K, V][]) => {\n setMap(entries instanceof Map ? new Map(entries) : new Map(entries));\n },\n remove: (key: K) => {\n setMap((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n },\n clear: () => setMap(new Map()),\n get: (key: K) => mapRef.current.get(key),\n has: (key: K) => mapRef.current.has(key),\n }),\n []\n );\n\n return [map, actions];\n}\n","import { useEffect, useState } from \"react\";\n\nexport interface UseMediaQueryOptions {\n defaultValue?: boolean;\n}\n\nexport function useMediaQuery(\n query: string,\n options: UseMediaQueryOptions = {}\n): boolean {\n const [matches, setMatches] = useState<boolean>(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return options.defaultValue ?? false;\n }\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return;\n }\n\n const mediaQueryList = window.matchMedia(query);\n const handler = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n setMatches(mediaQueryList.matches);\n\n if (mediaQueryList.addEventListener) {\n mediaQueryList.addEventListener(\"change\", handler);\n return () => mediaQueryList.removeEventListener(\"change\", handler);\n }\n\n mediaQueryList.addListener(handler);\n return () => mediaQueryList.removeListener(handler);\n }, [query]);\n\n return matches;\n}\n","import { useEffect, useRef } from \"react\";\n\ntype PossibleRef<T extends HTMLElement> = React.RefObject<T>;\n\nexport function useOnClickOutside<T extends HTMLElement>(\n ref: PossibleRef<T> | Array<PossibleRef<T>>,\n handler: (event: MouseEvent | TouchEvent | PointerEvent) => void,\n eventType: \"mousedown\" | \"mouseup\" | \"click\" | \"touchstart\" | \"pointerdown\" =\n \"mousedown\",\n options?: AddEventListenerOptions | boolean\n): void {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const refs = Array.isArray(ref) ? ref : [ref];\n const listener = (event: MouseEvent | TouchEvent | PointerEvent) => {\n const target = event.target;\n if (typeof Node === \"undefined\" || !(target instanceof Node)) {\n return;\n }\n\n const clickedInside = refs.some((currentRef) => {\n const node = currentRef.current;\n return node ? node.contains(target) : false;\n });\n\n if (!clickedInside) {\n handlerRef.current(event);\n }\n };\n\n document.addEventListener(eventType, listener, options);\n return () => {\n document.removeEventListener(eventType, listener, options);\n };\n }, [eventType, options, ref]);\n}\n","import { useEffect, useRef } from \"react\";\n\nexport function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T>();\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref.current;\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\ntype TargetElement<T extends Element> = React.RefObject<T> | T | null;\n\nconst isRefObject = <T extends Element>(\n value: unknown\n): value is React.RefObject<T> => !!value && typeof value === \"object\" && \"current\" in value;\n\nexport function useResizeObserver<T extends Element>(\n target: TargetElement<T>,\n onResize?: (entry: ResizeObserverEntry) => void,\n options?: ResizeObserverOptions\n): ResizeObserverEntry | null {\n const callbackRef = useRef(onResize);\n const entryRef = useRef<ResizeObserverEntry | null>(null);\n const [entry, setEntry] = useState<ResizeObserverEntry | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n callbackRef.current = onResize;\n }, [onResize]);\n\n useEffect(() => {\n if (typeof ResizeObserver === \"undefined\") {\n return;\n }\n\n const element =\n typeof Element !== \"undefined\" && target instanceof Element\n ? target\n : isRefObject<T>(target)\n ? target.current\n : null;\n if (!element) {\n return;\n }\n\n const observer = new ResizeObserver((entries) => {\n const firstEntry = entries[0];\n entryRef.current = firstEntry;\n if (callbackRef.current) {\n callbackRef.current(firstEntry);\n } else {\n setEntry(firstEntry);\n }\n });\n\n observer.observe(element, options);\n return () => observer.disconnect();\n }, [options, target]);\n\n return callbackRef.current ? entryRef.current : entry;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface SessionStorageOptions<T> {\n initializeWithValue?: boolean;\n serialize?: (value: T) => string;\n deserialize?: (value: string) => T;\n listenToStorageChanges?: boolean;\n}\n\ntype StoredSetter<T> = (value: T | ((current: T) => T)) => void;\n\nexport function useSessionStorage<T>(\n key: string,\n initialValue: T,\n options: SessionStorageOptions<T> = {}\n): [T, StoredSetter<T>] {\n const {\n initializeWithValue = true,\n serialize = JSON.stringify,\n deserialize = JSON.parse as (value: string) => T,\n listenToStorageChanges = false,\n } = options;\n\n const initialValueRef = useRef(initialValue);\n\n const readValue = useCallback(() => {\n if (typeof window === \"undefined\") {\n return initialValueRef.current;\n }\n if (!initializeWithValue) {\n return initialValueRef.current;\n }\n try {\n const item = window.sessionStorage.getItem(key);\n return item ? deserialize(item) : initialValueRef.current;\n } catch {\n return initialValueRef.current;\n }\n }, [deserialize, initializeWithValue, key]);\n\n const [storedValue, setStoredValue] = useState<T>(() => readValue());\n\n const setValue: StoredSetter<T> = useCallback(\n (value) => {\n setStoredValue((current) => {\n const valueToStore =\n typeof value === \"function\"\n ? (value as (current: T) => T)(current)\n : value;\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.setItem(key, serialize(valueToStore));\n } catch {\n // Ignore write errors (quota/security)\n }\n }\n return valueToStore;\n });\n },\n [key, serialize]\n );\n\n useEffect(() => {\n setStoredValue(readValue());\n }, [readValue]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !listenToStorageChanges) {\n return;\n }\n\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key !== key) {\n return;\n }\n if (event.newValue === null) {\n setStoredValue(initialValueRef.current);\n return;\n }\n try {\n setStoredValue(deserialize(event.newValue));\n } catch {\n setStoredValue(initialValueRef.current);\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [deserialize, key, listenToStorageChanges]);\n\n return [storedValue, setValue];\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nexport interface ThrottleOptions {\n leading?: boolean;\n trailing?: boolean;\n}\n\nexport function useThrottle<T>(\n value: T,\n interval: number,\n options: ThrottleOptions = {}\n): T {\n const leading = options.leading ?? true;\n const trailing = options.trailing ?? true;\n const wait = Math.max(0, interval);\n\n const [throttledValue, setThrottledValue] = useState<T>(value);\n const lastExecutedRef = useRef<number>(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingValueRef = useRef<T | null>(null);\n\n useEffect(() => {\n if (wait === 0) {\n setThrottledValue(value);\n return;\n }\n\n const now = Date.now();\n\n if (lastExecutedRef.current === 0) {\n lastExecutedRef.current = now;\n if (leading) {\n setThrottledValue(value);\n return;\n }\n if (trailing && !timeoutRef.current) {\n pendingValueRef.current = value;\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n if (pendingValueRef.current !== null) {\n setThrottledValue(pendingValueRef.current);\n pendingValueRef.current = null;\n lastExecutedRef.current = Date.now();\n }\n }, wait);\n }\n return;\n }\n\n const elapsed = now - lastExecutedRef.current;\n\n if (elapsed >= wait && leading) {\n setThrottledValue(value);\n lastExecutedRef.current = now;\n pendingValueRef.current = null;\n return;\n }\n\n if (trailing) {\n pendingValueRef.current = value;\n if (!timeoutRef.current) {\n const remaining = Math.max(wait - elapsed, 0);\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n if (pendingValueRef.current !== null) {\n setThrottledValue(pendingValueRef.current);\n pendingValueRef.current = null;\n lastExecutedRef.current = Date.now();\n }\n }, remaining);\n }\n }\n }, [leading, trailing, value, wait]);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return throttledValue;\n}\n"],"names":["useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","useDebounceCallback","callback","delay","options","callbackRef","useRef","timeoutRef","maxTimeoutRef","lastArgsRef","leading","trailing","maxWait","wait","Math","max","current","clearTimers","useCallback","clearTimeout","invoke","args","debouncedCallback","setTimeout","maxDelay","cancel","flush","useEventListener","eventName","handler","element","savedHandler","isWindow","Window","isDocument","Document","target","HTMLElement","value","addEventListener","listener","event","currentHandler","handleEvent","removeEventListener","defaultValue","setValue","useState","setTrue","setFalse","toggle","resetDelay","copiedText","setCopiedText","isSupported","useMemo","navigator","clipboard","document","queryCommandSupported","resetCopied","copy","async","text","shouldUseClipboardApi","writeText","textarea","createElement","setAttribute","style","position","left","top","body","appendChild","focus","select","success","execCommand","removeChild","debouncedValue","setDebouncedValue","next","ref","isHovered","setIsHovered","handleEnter","handleLeave","isClient","setIsClient","key","initialValue","initializeWithValue","serialize","JSON","stringify","deserialize","parse","listenToStorageChanges","initialValueRef","readValue","item","localStorage","getItem","storedValue","setStoredValue","valueToStore","setItem","handleStorageChange","newValue","initialState","map","setMap","Map","Array","isArray","mapRef","actions","set","prev","setAll","entries","remove","delete","clear","get","has","query","matches","setMatches","matchMedia","mediaQueryList","addListener","removeListener","eventType","handlerRef","refs","Node","some","currentRef","node","contains","onResize","entryRef","entry","setEntry","ResizeObserver","Element","observer","firstEntry","observe","disconnect","sessionStorage","interval","throttledValue","setThrottledValue","lastExecutedRef","pendingValueRef","now","Date","elapsed","remaining"],"mappings":"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"}
1
+ {"version":3,"file":"opensite-hooks.umd.js","sources":["../../src/core/useIsomorphicLayoutEffect.ts","../../src/core/useDebounceCallback.ts","../../src/core/useDebounceValue.ts","../../src/core/useEventListener.ts","../../src/core/useIsClient.ts","../../src/core/useMap.ts","../../src/core/websiteExtractorTypes.ts","../../src/core/websiteExtractorService.ts","../../src/core/useWebsiteExtractorBase.ts","../../src/core/useOpenGraphExtractor.ts","../../src/core/useBoolean.ts","../../src/core/useCopyToClipboard.ts","../../src/core/useHover.ts","../../src/core/useLocalStorage.ts","../../src/core/useMediaQuery.ts","../../src/core/useOnClickOutside.ts","../../src/core/usePrevious.ts","../../src/core/useResizeObserver.ts","../../src/core/useSessionStorage.ts","../../src/core/useThrottle.ts","../../src/core/useWebsiteLinksExtractor.ts","../../src/core/useWebsiteMetaExtractor.ts","../../src/core/useWebsiteRssExtractor.ts","../../src/core/useWebsiteSchemaExtractor.ts"],"sourcesContent":["import { useEffect, useLayoutEffect } from \"react\";\n\nexport const useIsomorphicLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\nexport interface DebounceOptions {\n leading?: boolean;\n trailing?: boolean;\n maxWait?: number;\n}\n\nexport interface DebouncedCallback<T extends (...args: any[]) => void> {\n debouncedCallback: (...args: Parameters<T>) => void;\n cancel: () => void;\n flush: () => void;\n}\n\nexport function useDebounceCallback<T extends (...args: any[]) => void>(\n callback: T,\n delay: number,\n options: DebounceOptions = {}\n): DebouncedCallback<T> {\n const callbackRef = useRef(callback);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const maxTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastArgsRef = useRef<Parameters<T> | null>(null);\n\n const leading = options.leading ?? false;\n const trailing = options.trailing ?? true;\n const maxWait = options.maxWait;\n const wait = Math.max(0, delay);\n\n useIsomorphicLayoutEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n const clearTimers = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (maxTimeoutRef.current) {\n clearTimeout(maxTimeoutRef.current);\n maxTimeoutRef.current = null;\n }\n }, []);\n\n const invoke = useCallback(() => {\n if (!lastArgsRef.current) {\n return;\n }\n const args = lastArgsRef.current;\n lastArgsRef.current = null;\n callbackRef.current(...args);\n }, []);\n\n const debouncedCallback = useCallback(\n (...args: Parameters<T>) => {\n lastArgsRef.current = args;\n\n const shouldInvokeLeading =\n leading && timeoutRef.current === null && maxTimeoutRef.current === null;\n if (shouldInvokeLeading) {\n invoke();\n }\n\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n if (trailing) {\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n if (lastArgsRef.current) {\n invoke();\n }\n if (maxTimeoutRef.current) {\n clearTimeout(maxTimeoutRef.current);\n maxTimeoutRef.current = null;\n }\n }, wait);\n }\n\n if (maxWait !== undefined && maxWait !== null && trailing) {\n if (!maxTimeoutRef.current) {\n const maxDelay = Math.max(0, maxWait);\n maxTimeoutRef.current = setTimeout(() => {\n maxTimeoutRef.current = null;\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (lastArgsRef.current) {\n invoke();\n }\n }, maxDelay);\n }\n }\n },\n [invoke, leading, trailing, maxWait, wait]\n );\n\n const cancel = useCallback(() => {\n clearTimers();\n lastArgsRef.current = null;\n }, [clearTimers]);\n\n const flush = useCallback(() => {\n if (!lastArgsRef.current) {\n return;\n }\n clearTimers();\n invoke();\n }, [clearTimers, invoke]);\n\n useEffect(() => () => cancel(), [cancel]);\n\n return { debouncedCallback, cancel, flush };\n}\n","import { useEffect, useState } from \"react\";\nimport { DebounceOptions, useDebounceCallback } from \"./useDebounceCallback.js\";\n\nexport function useDebounceValue<T>(\n value: T,\n delay: number,\n options?: DebounceOptions\n): T {\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\n const { debouncedCallback, cancel } = useDebounceCallback(\n (next: T) => {\n setDebouncedValue(next);\n },\n delay,\n options\n );\n\n useEffect(() => {\n debouncedCallback(value);\n }, [debouncedCallback, value]);\n\n useEffect(() => () => cancel(), [cancel]);\n\n return debouncedValue;\n}\n","import { useEffect, useRef } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\ntype EventTargetLike = Window | Document | HTMLElement | null;\ntype ElementRef = React.RefObject<HTMLElement>;\n\nconst isRefObject = (value: unknown): value is ElementRef =>\n !!value && typeof value === \"object\" && \"current\" in value;\n\nexport function useEventListener<K extends keyof WindowEventMap>(\n eventName: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: Window,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener<K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: Document,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener<K extends keyof HTMLElementEventMap>(\n eventName: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: ElementRef,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener<K extends keyof HTMLElementEventMap>(\n eventName: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: HTMLElement,\n options?: AddEventListenerOptions | boolean\n): void;\nexport function useEventListener(\n eventName: string,\n handler: EventListenerOrEventListenerObject,\n element?: EventTargetLike | ElementRef,\n options?: AddEventListenerOptions | boolean\n): void {\n const savedHandler = useRef(handler);\n\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const isWindow =\n typeof Window !== \"undefined\" && element instanceof Window;\n const isDocument =\n typeof Document !== \"undefined\" && element instanceof Document;\n\n const target: EventTargetLike | null =\n element === undefined\n ? typeof window !== \"undefined\"\n ? window\n : null\n : isWindow || isDocument\n ? element\n : typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement\n ? element\n : isRefObject(element)\n ? element.current\n : null;\n\n if (!target?.addEventListener) {\n return;\n }\n\n const listener = (event: Event) => {\n const currentHandler = savedHandler.current;\n if (typeof currentHandler === \"function\") {\n currentHandler(event);\n } else {\n currentHandler.handleEvent(event);\n }\n };\n\n target.addEventListener(eventName, listener, options);\n\n return () => {\n target.removeEventListener(eventName, listener, options);\n };\n }, [eventName, element, options]);\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useIsClient(): boolean {\n const [isClient, setIsClient] = useState(false);\n\n useEffect(() => {\n setIsClient(true);\n }, []);\n\n return isClient;\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface MapActions<K, V> {\n set: (key: K, value: V) => void;\n setAll: (entries: Map<K, V> | [K, V][]) => void;\n remove: (key: K) => void;\n clear: () => void;\n get: (key: K) => V | undefined;\n has: (key: K) => boolean;\n}\n\nexport function useMap<K, V>(\n initialState?: Map<K, V> | [K, V][]\n): [Map<K, V>, MapActions<K, V>] {\n const [map, setMap] = useState<Map<K, V>>(() => {\n if (initialState instanceof Map) {\n return new Map(initialState);\n }\n if (Array.isArray(initialState)) {\n return new Map(initialState);\n }\n return new Map();\n });\n\n const mapRef = useRef(map);\n\n useEffect(() => {\n mapRef.current = map;\n }, [map]);\n\n const actions = useMemo<MapActions<K, V>>(\n () => ({\n set: (key: K, value: V) => {\n setMap((prev) => {\n const next = new Map(prev);\n next.set(key, value);\n return next;\n });\n },\n setAll: (entries: Map<K, V> | [K, V][]) => {\n setMap(entries instanceof Map ? new Map(entries) : new Map(entries));\n },\n remove: (key: K) => {\n setMap((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n },\n clear: () => setMap(new Map()),\n get: (key: K) => mapRef.current.get(key),\n has: (key: K) => mapRef.current.has(key),\n }),\n []\n );\n\n return [map, actions];\n}\n","export interface WebsiteExtractCacheMeta {\n hit: boolean;\n ageSeconds: number;\n ttlSeconds: number;\n staleWhileRevalidateSeconds: number;\n}\n\nexport interface WebsiteExtractMeta {\n requestedUrl: string;\n finalUrl: string;\n url: string;\n normalizedUrl: string;\n status: number;\n contentType: string;\n fetchedAt: string;\n bodyBytes: number;\n bodyTruncated: boolean;\n maxBodyBytes: number;\n cache: WebsiteExtractCacheMeta;\n}\n\nexport interface WebsiteExtractorError {\n message: string;\n status?: number;\n raw?: unknown;\n}\n\nexport interface WebsiteExtractorOptions {\n url?: string;\n apiKey?: string;\n baseUrl?: string;\n debounceMs?: number;\n refreshDebounceMs?: number;\n enabled?: boolean;\n cache?: boolean;\n}\n\nexport interface WebsiteExtractorState<TData, TRaw = TData> {\n loading: boolean;\n data?: TData;\n raw?: TRaw;\n meta?: WebsiteExtractMeta;\n error?: WebsiteExtractorError;\n}\n\nexport interface WebsiteExtractorResult<TData, TRaw = TData>\n extends WebsiteExtractorState<TData, TRaw> {\n refresh: () => void;\n}\n\nexport type WebsiteExtractorResponse<TPayload> = WebsiteExtractMeta & TPayload;\n\nexport interface WebsiteExtractorRequest {\n endpoint: string;\n url: string;\n apiKey?: string;\n baseUrl?: string;\n signal?: AbortSignal;\n}\n\nexport type WebsiteExtractorClientResult<T> =\n | { ok: true; response: T }\n | { ok: false; error: WebsiteExtractorError };\n\nexport const DEFAULT_WEBSITE_EXTRACTOR_BASE_URL = \"https://octane.buzz\";\n\nexport const DEFAULT_EXTRACTOR_DEBOUNCE_MS = 250;\n\nexport const DEFAULT_EXTRACTOR_REFRESH_DEBOUNCE_MS = 150;\n\nexport const DEFAULT_EXTRACTOR_ENABLED = true;\n\nexport const DEFAULT_EXTRACTOR_CACHE = true;\n\nexport function extractWebsiteMeta(response: WebsiteExtractMeta): WebsiteExtractMeta {\n const {\n requestedUrl,\n finalUrl,\n url,\n normalizedUrl,\n status,\n contentType,\n fetchedAt,\n bodyBytes,\n bodyTruncated,\n maxBodyBytes,\n cache,\n } = response;\n\n return {\n requestedUrl,\n finalUrl,\n url,\n normalizedUrl,\n status,\n contentType,\n fetchedAt,\n bodyBytes,\n bodyTruncated,\n maxBodyBytes,\n cache,\n };\n}\n\nexport function stripWebsiteMeta<TResponse extends WebsiteExtractMeta>(\n response: TResponse\n): Omit<TResponse, keyof WebsiteExtractMeta> {\n const {\n requestedUrl: _requestedUrl,\n finalUrl: _finalUrl,\n url: _url,\n normalizedUrl: _normalizedUrl,\n status: _status,\n contentType: _contentType,\n fetchedAt: _fetchedAt,\n bodyBytes: _bodyBytes,\n bodyTruncated: _bodyTruncated,\n maxBodyBytes: _maxBodyBytes,\n cache: _cache,\n ...payload\n } = response;\n\n return payload;\n}\n","import {\n DEFAULT_WEBSITE_EXTRACTOR_BASE_URL,\n type WebsiteExtractorClientResult,\n type WebsiteExtractorError,\n type WebsiteExtractorRequest,\n} from \"./websiteExtractorTypes.js\";\n\nconst EXTRACTOR_PATH = \"/api/v1/extract\";\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\nexport function buildWebsiteExtractorUrl(request: WebsiteExtractorRequest): string {\n const baseUrl = normalizeBaseUrl(\n request.baseUrl ?? DEFAULT_WEBSITE_EXTRACTOR_BASE_URL\n );\n const params = new URLSearchParams();\n\n if (request.apiKey) {\n params.set(\"api_key\", request.apiKey);\n }\n\n params.set(\"url\", request.url);\n\n return `${baseUrl}${EXTRACTOR_PATH}/${request.endpoint}?${params.toString()}`;\n}\n\nexport async function fetchWebsiteExtractor<TResponse>(\n request: WebsiteExtractorRequest\n): Promise<WebsiteExtractorClientResult<TResponse>> {\n if (!request.url || request.url.trim().length === 0) {\n return {\n ok: false,\n error: {\n message: \"URL is required.\",\n },\n };\n }\n\n const endpoint = buildWebsiteExtractorUrl(request);\n\n try {\n const response = await fetch(endpoint, {\n method: \"GET\",\n signal: request.signal,\n });\n\n let payload: unknown = null;\n try {\n payload = await response.json();\n } catch {\n payload = null;\n }\n\n if (!response.ok) {\n const errorPayload = payload as { error?: string; status?: number } | null;\n const error: WebsiteExtractorError = {\n message:\n errorPayload?.error ??\n `Request failed with status ${response.status}.`,\n status: errorPayload?.status ?? response.status,\n raw: payload,\n };\n\n return { ok: false, error };\n }\n\n return { ok: true, response: payload as TResponse };\n } catch (error) {\n if (request.signal?.aborted) {\n return {\n ok: false,\n error: {\n message: \"Request aborted.\",\n },\n };\n }\n\n return {\n ok: false,\n error: {\n message:\n error instanceof Error ? error.message : \"Request failed unexpectedly.\",\n raw: error,\n },\n };\n }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useDebounceCallback } from \"./useDebounceCallback.js\";\nimport { useDebounceValue } from \"./useDebounceValue.js\";\nimport { useIsClient } from \"./useIsClient.js\";\nimport { useMap } from \"./useMap.js\";\nimport { fetchWebsiteExtractor } from \"./websiteExtractorService.js\";\nimport {\n DEFAULT_EXTRACTOR_CACHE,\n DEFAULT_EXTRACTOR_DEBOUNCE_MS,\n DEFAULT_EXTRACTOR_ENABLED,\n DEFAULT_EXTRACTOR_REFRESH_DEBOUNCE_MS,\n DEFAULT_WEBSITE_EXTRACTOR_BASE_URL,\n extractWebsiteMeta,\n stripWebsiteMeta,\n type WebsiteExtractorOptions,\n type WebsiteExtractorResult,\n type WebsiteExtractorState,\n type WebsiteExtractMeta,\n} from \"./websiteExtractorTypes.js\";\n\ninterface CachedExtractorEntry<TData, TRaw extends WebsiteExtractMeta> {\n data: TData;\n raw: TRaw;\n meta: WebsiteExtractMeta;\n}\n\ninterface UseWebsiteExtractorBaseConfig<\n TResponse extends WebsiteExtractMeta,\n TData,\n> {\n endpoint: string;\n options: WebsiteExtractorOptions;\n selectData: (\n payload: Omit<TResponse, keyof WebsiteExtractMeta>,\n raw: TResponse,\n meta: WebsiteExtractMeta\n ) => TData;\n shouldSkip?: (url: string) => boolean;\n}\n\nexport function useWebsiteExtractorBase<\n TResponse extends WebsiteExtractMeta,\n TData,\n>(config: UseWebsiteExtractorBaseConfig<TResponse, TData>): WebsiteExtractorResult<\n TData,\n TResponse\n> {\n const { endpoint, options, selectData, shouldSkip } = config;\n const isClient = useIsClient();\n const [state, setState] = useState<WebsiteExtractorState<TData, TResponse>>({\n loading: false,\n });\n\n const [, cacheActions] = useMap<\n string,\n CachedExtractorEntry<TData, TResponse>\n >();\n const cacheEnabled = options.cache ?? DEFAULT_EXTRACTOR_CACHE;\n const enabled = options.enabled ?? DEFAULT_EXTRACTOR_ENABLED;\n const debounceMs = options.debounceMs ?? DEFAULT_EXTRACTOR_DEBOUNCE_MS;\n const refreshDebounceMs =\n options.refreshDebounceMs ?? DEFAULT_EXTRACTOR_REFRESH_DEBOUNCE_MS;\n\n const normalizedUrl = useMemo(() => {\n return options.url?.trim() ?? \"\";\n }, [options.url]);\n\n const debouncedUrl = useDebounceValue(normalizedUrl, debounceMs);\n\n const refreshCounterRef = useRef(0);\n const lastRefreshHandledRef = useRef(0);\n const [refreshToken, setRefreshToken] = useState(0);\n\n const { debouncedCallback: scheduleRefresh, cancel: cancelRefresh } =\n useDebounceCallback(() => {\n refreshCounterRef.current += 1;\n setRefreshToken(refreshCounterRef.current);\n }, refreshDebounceMs);\n\n const refresh = useCallback(() => {\n scheduleRefresh();\n }, [scheduleRefresh]);\n\n useEffect(() => () => cancelRefresh(), [cancelRefresh]);\n\n const requestKey = useMemo(() => {\n if (!debouncedUrl) {\n return \"\";\n }\n\n const baseUrl = options.baseUrl ?? DEFAULT_WEBSITE_EXTRACTOR_BASE_URL;\n const apiKey = options.apiKey ?? \"\";\n return `${endpoint}:${baseUrl}:${apiKey}:${debouncedUrl}`;\n }, [\n endpoint,\n options.apiKey,\n options.baseUrl,\n debouncedUrl,\n ]);\n\n const inFlightControllerRef = useRef<AbortController | null>(null);\n\n useEffect(() => {\n if (!isClient) {\n return;\n }\n\n if (!enabled || !debouncedUrl) {\n setState({ loading: false });\n return;\n }\n\n if (shouldSkip?.(debouncedUrl)) {\n setState({ loading: false });\n return;\n }\n\n const forceRefresh = refreshToken !== lastRefreshHandledRef.current;\n if (forceRefresh) {\n lastRefreshHandledRef.current = refreshToken;\n }\n\n if (cacheEnabled && !forceRefresh) {\n const cached = cacheActions.get(requestKey);\n if (cached) {\n setState({\n loading: false,\n data: cached.data,\n raw: cached.raw,\n meta: cached.meta,\n });\n return;\n }\n }\n\n inFlightControllerRef.current?.abort();\n const controller = new AbortController();\n inFlightControllerRef.current = controller;\n\n setState((prev) => ({\n ...prev,\n loading: true,\n error: undefined,\n }));\n\n fetchWebsiteExtractor<TResponse>({\n endpoint,\n url: debouncedUrl,\n apiKey: options.apiKey,\n baseUrl: options.baseUrl,\n signal: controller.signal,\n })\n .then((result) => {\n if (controller.signal.aborted) {\n return;\n }\n\n if (!result.ok) {\n setState((prev) => ({\n ...prev,\n loading: false,\n error: result.error,\n }));\n return;\n }\n\n const raw = result.response;\n const meta = extractWebsiteMeta(raw);\n const payload = stripWebsiteMeta(raw);\n const data = selectData(payload, raw, meta);\n\n if (cacheEnabled) {\n cacheActions.set(requestKey, { data, raw, meta });\n }\n\n setState({\n loading: false,\n data,\n raw,\n meta,\n });\n })\n .catch((error) => {\n if (controller.signal.aborted) {\n return;\n }\n\n setState((prev) => ({\n ...prev,\n loading: false,\n error: {\n message:\n error instanceof Error\n ? error.message\n : \"Request failed unexpectedly.\",\n raw: error,\n },\n }));\n });\n\n return () => {\n controller.abort();\n };\n }, [\n cacheActions,\n cacheEnabled,\n debouncedUrl,\n enabled,\n endpoint,\n isClient,\n options.apiKey,\n options.baseUrl,\n requestKey,\n refreshToken,\n selectData,\n shouldSkip,\n ]);\n\n return useMemo(\n () => ({\n ...state,\n refresh,\n }),\n [refresh, state]\n );\n}\n","import { useCallback, useMemo } from \"react\";\nimport { useWebsiteExtractorBase } from \"./useWebsiteExtractorBase.js\";\nimport type {\n WebsiteExtractorOptions,\n WebsiteExtractorResponse,\n WebsiteExtractorResult,\n WebsiteExtractMeta,\n} from \"./websiteExtractorTypes.js\";\n\nexport interface OpenGraphImage {\n url?: string | null;\n height?: string | null;\n width?: string | null;\n}\n\nexport interface OpenGraphVideo {\n url?: string | null;\n height?: string | null;\n width?: string | null;\n}\n\nexport interface OpenGraphData {\n description?: string | null;\n title?: string | null;\n site_name?: string | null;\n image?: OpenGraphImage | null;\n video?: OpenGraphVideo | null;\n url?: string | null;\n ogType?: string | null;\n}\n\nexport interface OpenGraphHtmlInferredData {\n description?: string | null;\n title?: string | null;\n type?: string | null;\n videoType?: string | null;\n url?: string | null;\n favicon?: string | null;\n images?: string[] | null;\n image?: string | null;\n site_name?: string | null;\n}\n\nexport interface OpenGraphHybridData {\n description?: string | null;\n title?: string | null;\n type?: string | null;\n image?: string | null;\n video?: string | null;\n videoType?: string | null;\n favicon?: string | null;\n site_name?: string | null;\n url?: string | null;\n videoWidth?: number | null;\n videoHeight?: number | null;\n}\n\nexport type OpenGraphResponse = WebsiteExtractorResponse<{\n openGraph: OpenGraphData;\n htmlInferred: OpenGraphHtmlInferredData;\n hybridGraph: OpenGraphHybridData;\n}>;\n\nexport interface OpenGraphSummary {\n description?: string;\n favicon?: string;\n image?: string;\n video?: string;\n videoType?: string;\n siteName?: string;\n title?: string;\n url: string;\n siteHost?: string;\n}\n\nexport interface OpenGraphExtractorOptions extends WebsiteExtractorOptions {\n skipPatterns?: RegExp[];\n}\n\nconst DEFAULT_SKIP_PATTERNS = [\n /search\\.google\\.com\\/local\\/reviews/i,\n /google\\.com\\/maps\\/place/i,\n /maps\\.google\\.com/i,\n /opentable\\.com/i,\n];\n\nconst pickFirstString = (\n ...values: Array<string | null | undefined>\n): string | undefined => {\n for (const value of values) {\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return undefined;\n};\n\nconst safeHost = (value: string | undefined): string | undefined => {\n if (!value) {\n return undefined;\n }\n\n try {\n return new URL(value).hostname;\n } catch {\n return undefined;\n }\n};\n\nexport function useOpenGraphExtractor(\n options: OpenGraphExtractorOptions\n): WebsiteExtractorResult<OpenGraphSummary, OpenGraphResponse> {\n const skipPatterns = useMemo(\n () => options.skipPatterns ?? DEFAULT_SKIP_PATTERNS,\n [options.skipPatterns]\n );\n\n const shouldSkip = useCallback(\n (url: string) => skipPatterns.some((pattern) => pattern.test(url)),\n [skipPatterns]\n );\n\n const selectData = useCallback(\n (\n payload: Omit<OpenGraphResponse, keyof WebsiteExtractMeta>,\n _raw: OpenGraphResponse,\n meta: WebsiteExtractMeta\n ): OpenGraphSummary => {\n const { openGraph, htmlInferred, hybridGraph } = payload;\n\n const description = pickFirstString(\n openGraph?.description,\n hybridGraph?.description,\n htmlInferred?.description\n );\n const title = pickFirstString(\n openGraph?.title,\n hybridGraph?.title,\n htmlInferred?.title\n );\n const siteName = pickFirstString(\n openGraph?.site_name,\n hybridGraph?.site_name,\n htmlInferred?.site_name\n );\n const favicon = pickFirstString(\n hybridGraph?.favicon,\n htmlInferred?.favicon\n );\n const image = pickFirstString(\n openGraph?.image?.url ?? undefined,\n hybridGraph?.image ?? undefined,\n htmlInferred?.image ?? undefined,\n htmlInferred?.images?.[0]\n );\n const video = pickFirstString(\n openGraph?.video?.url ?? undefined,\n hybridGraph?.video ?? undefined\n );\n const videoType = pickFirstString(\n hybridGraph?.videoType,\n htmlInferred?.videoType\n );\n const resolvedUrl =\n pickFirstString(\n meta.url,\n openGraph?.url ?? undefined,\n hybridGraph?.url ?? undefined,\n htmlInferred?.url ?? undefined,\n meta.finalUrl,\n meta.normalizedUrl,\n meta.requestedUrl\n ) ?? \"\";\n\n return {\n description,\n favicon,\n image,\n video,\n videoType,\n siteName,\n title,\n url: resolvedUrl,\n siteHost: safeHost(resolvedUrl),\n };\n },\n []\n );\n\n return useWebsiteExtractorBase<OpenGraphResponse, OpenGraphSummary>({\n endpoint: \"open-graph\",\n options,\n selectData,\n shouldSkip,\n });\n}\n","import { useCallback, useState } from \"react\";\n\nexport interface UseBooleanResult {\n value: boolean;\n setValue: React.Dispatch<React.SetStateAction<boolean>>;\n setTrue: () => void;\n setFalse: () => void;\n toggle: () => void;\n}\n\nexport function useBoolean(defaultValue = false): UseBooleanResult {\n const [value, setValue] = useState<boolean>(defaultValue);\n\n const setTrue = useCallback(() => setValue(true), []);\n const setFalse = useCallback(() => setValue(false), []);\n const toggle = useCallback(() => setValue((current) => !current), []);\n\n return { value, setValue, setTrue, setFalse, toggle };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface UseCopyToClipboardOptions {\n resetDelay?: number;\n}\n\nexport interface CopyToClipboardResult {\n copy: (text: string) => Promise<boolean>;\n copiedText: string | null;\n isSupported: boolean;\n}\n\nexport function useCopyToClipboard(\n options: UseCopyToClipboardOptions = {}\n): CopyToClipboardResult {\n const resetDelay = options.resetDelay ?? 2000;\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [copiedText, setCopiedText] = useState<string | null>(null);\n\n const isSupported = useMemo(() => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n return true;\n }\n if (typeof document === \"undefined\") {\n return false;\n }\n if (typeof document.queryCommandSupported !== \"function\") {\n return false;\n }\n return document.queryCommandSupported(\"copy\");\n }, []);\n\n const resetCopied = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n setCopiedText(null);\n }, resetDelay);\n }, [resetDelay]);\n\n const copy = useCallback(\n async (text: string) => {\n if (!isSupported) {\n return false;\n }\n\n const shouldUseClipboardApi =\n typeof navigator !== \"undefined\" && !!navigator.clipboard;\n\n try {\n if (shouldUseClipboardApi) {\n await navigator.clipboard.writeText(text);\n } else if (typeof document !== \"undefined\") {\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"fixed\";\n textarea.style.left = \"-9999px\";\n textarea.style.top = \"0\";\n document.body.appendChild(textarea);\n textarea.focus();\n textarea.select();\n const success = document.execCommand(\"copy\");\n document.body.removeChild(textarea);\n if (!success) {\n return false;\n }\n }\n\n setCopiedText(text);\n resetCopied();\n return true;\n } catch {\n return false;\n }\n },\n [isSupported, resetCopied]\n );\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return { copy, copiedText, isSupported };\n}\n","import { useCallback, useState } from \"react\";\nimport { useEventListener } from \"./useEventListener.js\";\n\nexport function useHover<T extends HTMLElement>(\n ref: React.RefObject<T>\n): boolean {\n const [isHovered, setIsHovered] = useState(false);\n\n const handleEnter = useCallback(() => {\n setIsHovered(true);\n }, []);\n\n const handleLeave = useCallback(() => {\n setIsHovered(false);\n }, []);\n\n useEventListener(\"pointerenter\", handleEnter, ref);\n useEventListener(\"pointerleave\", handleLeave, ref);\n\n return isHovered;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface StorageOptions<T> {\n initializeWithValue?: boolean;\n serialize?: (value: T) => string;\n deserialize?: (value: string) => T;\n listenToStorageChanges?: boolean;\n}\n\ntype StoredSetter<T> = (value: T | ((current: T) => T)) => void;\n\nexport function useLocalStorage<T>(\n key: string,\n initialValue: T,\n options: StorageOptions<T> = {}\n): [T, StoredSetter<T>] {\n const {\n initializeWithValue = true,\n serialize = JSON.stringify,\n deserialize = JSON.parse as (value: string) => T,\n listenToStorageChanges = true,\n } = options;\n\n const initialValueRef = useRef(initialValue);\n\n const readValue = useCallback(() => {\n if (typeof window === \"undefined\") {\n return initialValueRef.current;\n }\n if (!initializeWithValue) {\n return initialValueRef.current;\n }\n try {\n const item = window.localStorage.getItem(key);\n return item ? deserialize(item) : initialValueRef.current;\n } catch {\n return initialValueRef.current;\n }\n }, [deserialize, initializeWithValue, key]);\n\n const [storedValue, setStoredValue] = useState<T>(() => readValue());\n\n const setValue: StoredSetter<T> = useCallback(\n (value) => {\n setStoredValue((current) => {\n const valueToStore =\n typeof value === \"function\"\n ? (value as (current: T) => T)(current)\n : value;\n if (typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(key, serialize(valueToStore));\n } catch {\n // Ignore write errors (quota/security)\n }\n }\n return valueToStore;\n });\n },\n [key, serialize]\n );\n\n useEffect(() => {\n setStoredValue(readValue());\n }, [readValue]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !listenToStorageChanges) {\n return;\n }\n\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key !== key) {\n return;\n }\n if (event.newValue === null) {\n setStoredValue(initialValueRef.current);\n return;\n }\n try {\n setStoredValue(deserialize(event.newValue));\n } catch {\n setStoredValue(initialValueRef.current);\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [deserialize, key, listenToStorageChanges]);\n\n return [storedValue, setValue];\n}\n","import { useEffect, useState } from \"react\";\n\nexport interface UseMediaQueryOptions {\n defaultValue?: boolean;\n}\n\nexport function useMediaQuery(\n query: string,\n options: UseMediaQueryOptions = {}\n): boolean {\n const [matches, setMatches] = useState<boolean>(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return options.defaultValue ?? false;\n }\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return;\n }\n\n const mediaQueryList = window.matchMedia(query);\n const handler = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n setMatches(mediaQueryList.matches);\n\n if (mediaQueryList.addEventListener) {\n mediaQueryList.addEventListener(\"change\", handler);\n return () => mediaQueryList.removeEventListener(\"change\", handler);\n }\n\n mediaQueryList.addListener(handler);\n return () => mediaQueryList.removeListener(handler);\n }, [query]);\n\n return matches;\n}\n","import { useEffect, useRef } from \"react\";\n\ntype PossibleRef<T extends HTMLElement> = React.RefObject<T>;\n\nexport function useOnClickOutside<T extends HTMLElement>(\n ref: PossibleRef<T> | Array<PossibleRef<T>>,\n handler: (event: MouseEvent | TouchEvent | PointerEvent) => void,\n eventType: \"mousedown\" | \"mouseup\" | \"click\" | \"touchstart\" | \"pointerdown\" =\n \"mousedown\",\n options?: AddEventListenerOptions | boolean\n): void {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const refs = Array.isArray(ref) ? ref : [ref];\n const listener = (event: MouseEvent | TouchEvent | PointerEvent) => {\n const target = event.target;\n if (typeof Node === \"undefined\" || !(target instanceof Node)) {\n return;\n }\n\n const clickedInside = refs.some((currentRef) => {\n const node = currentRef.current;\n return node ? node.contains(target) : false;\n });\n\n if (!clickedInside) {\n handlerRef.current(event);\n }\n };\n\n document.addEventListener(eventType, listener, options);\n return () => {\n document.removeEventListener(eventType, listener, options);\n };\n }, [eventType, options, ref]);\n}\n","import { useEffect, useRef } from \"react\";\n\nexport function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T>();\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref.current;\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useIsomorphicLayoutEffect } from \"./useIsomorphicLayoutEffect.js\";\n\ntype TargetElement<T extends Element> = React.RefObject<T> | T | null;\n\nconst isRefObject = <T extends Element>(\n value: unknown\n): value is React.RefObject<T> => !!value && typeof value === \"object\" && \"current\" in value;\n\nexport function useResizeObserver<T extends Element>(\n target: TargetElement<T>,\n onResize?: (entry: ResizeObserverEntry) => void,\n options?: ResizeObserverOptions\n): ResizeObserverEntry | null {\n const callbackRef = useRef(onResize);\n const entryRef = useRef<ResizeObserverEntry | null>(null);\n const [entry, setEntry] = useState<ResizeObserverEntry | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n callbackRef.current = onResize;\n }, [onResize]);\n\n useEffect(() => {\n if (typeof ResizeObserver === \"undefined\") {\n return;\n }\n\n const element =\n typeof Element !== \"undefined\" && target instanceof Element\n ? target\n : isRefObject<T>(target)\n ? target.current\n : null;\n if (!element) {\n return;\n }\n\n const observer = new ResizeObserver((entries) => {\n const firstEntry = entries[0];\n entryRef.current = firstEntry;\n if (callbackRef.current) {\n callbackRef.current(firstEntry);\n } else {\n setEntry(firstEntry);\n }\n });\n\n observer.observe(element, options);\n return () => observer.disconnect();\n }, [options, target]);\n\n return callbackRef.current ? entryRef.current : entry;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface SessionStorageOptions<T> {\n initializeWithValue?: boolean;\n serialize?: (value: T) => string;\n deserialize?: (value: string) => T;\n listenToStorageChanges?: boolean;\n}\n\ntype StoredSetter<T> = (value: T | ((current: T) => T)) => void;\n\nexport function useSessionStorage<T>(\n key: string,\n initialValue: T,\n options: SessionStorageOptions<T> = {}\n): [T, StoredSetter<T>] {\n const {\n initializeWithValue = true,\n serialize = JSON.stringify,\n deserialize = JSON.parse as (value: string) => T,\n listenToStorageChanges = false,\n } = options;\n\n const initialValueRef = useRef(initialValue);\n\n const readValue = useCallback(() => {\n if (typeof window === \"undefined\") {\n return initialValueRef.current;\n }\n if (!initializeWithValue) {\n return initialValueRef.current;\n }\n try {\n const item = window.sessionStorage.getItem(key);\n return item ? deserialize(item) : initialValueRef.current;\n } catch {\n return initialValueRef.current;\n }\n }, [deserialize, initializeWithValue, key]);\n\n const [storedValue, setStoredValue] = useState<T>(() => readValue());\n\n const setValue: StoredSetter<T> = useCallback(\n (value) => {\n setStoredValue((current) => {\n const valueToStore =\n typeof value === \"function\"\n ? (value as (current: T) => T)(current)\n : value;\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.setItem(key, serialize(valueToStore));\n } catch {\n // Ignore write errors (quota/security)\n }\n }\n return valueToStore;\n });\n },\n [key, serialize]\n );\n\n useEffect(() => {\n setStoredValue(readValue());\n }, [readValue]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !listenToStorageChanges) {\n return;\n }\n\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key !== key) {\n return;\n }\n if (event.newValue === null) {\n setStoredValue(initialValueRef.current);\n return;\n }\n try {\n setStoredValue(deserialize(event.newValue));\n } catch {\n setStoredValue(initialValueRef.current);\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [deserialize, key, listenToStorageChanges]);\n\n return [storedValue, setValue];\n}\n","import { useEffect, useRef, useState } from \"react\";\n\nexport interface ThrottleOptions {\n leading?: boolean;\n trailing?: boolean;\n}\n\nexport function useThrottle<T>(\n value: T,\n interval: number,\n options: ThrottleOptions = {}\n): T {\n const leading = options.leading ?? true;\n const trailing = options.trailing ?? true;\n const wait = Math.max(0, interval);\n\n const [throttledValue, setThrottledValue] = useState<T>(value);\n const lastExecutedRef = useRef<number>(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingValueRef = useRef<T | null>(null);\n\n useEffect(() => {\n if (wait === 0) {\n setThrottledValue(value);\n return;\n }\n\n const now = Date.now();\n\n if (lastExecutedRef.current === 0) {\n lastExecutedRef.current = now;\n if (leading) {\n setThrottledValue(value);\n return;\n }\n if (trailing && !timeoutRef.current) {\n pendingValueRef.current = value;\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n if (pendingValueRef.current !== null) {\n setThrottledValue(pendingValueRef.current);\n pendingValueRef.current = null;\n lastExecutedRef.current = Date.now();\n }\n }, wait);\n }\n return;\n }\n\n const elapsed = now - lastExecutedRef.current;\n\n if (elapsed >= wait && leading) {\n setThrottledValue(value);\n lastExecutedRef.current = now;\n pendingValueRef.current = null;\n return;\n }\n\n if (trailing) {\n pendingValueRef.current = value;\n if (!timeoutRef.current) {\n const remaining = Math.max(wait - elapsed, 0);\n timeoutRef.current = setTimeout(() => {\n timeoutRef.current = null;\n if (pendingValueRef.current !== null) {\n setThrottledValue(pendingValueRef.current);\n pendingValueRef.current = null;\n lastExecutedRef.current = Date.now();\n }\n }, remaining);\n }\n }\n }, [leading, trailing, value, wait]);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return throttledValue;\n}\n","import { useCallback } from \"react\";\nimport { useWebsiteExtractorBase } from \"./useWebsiteExtractorBase.js\";\nimport type {\n WebsiteExtractorOptions,\n WebsiteExtractorResponse,\n WebsiteExtractorResult,\n WebsiteExtractMeta,\n} from \"./websiteExtractorTypes.js\";\n\nexport interface WebsiteLinkRecord {\n url: string;\n text: string;\n isExternal: boolean;\n domain?: string | null;\n}\n\nexport interface WebsiteLinksPayload {\n totalLinks: number;\n uniqueDomains: number;\n links: WebsiteLinkRecord[];\n}\n\nexport type WebsiteLinksResponse = WebsiteExtractorResponse<WebsiteLinksPayload>;\n\nexport function useWebsiteLinksExtractor(\n options: WebsiteExtractorOptions\n): WebsiteExtractorResult<WebsiteLinksPayload, WebsiteLinksResponse> {\n const selectData = useCallback(\n (\n payload: Omit<WebsiteLinksResponse, keyof WebsiteExtractMeta>\n ): WebsiteLinksPayload => {\n return {\n totalLinks: payload.totalLinks ?? 0,\n uniqueDomains: payload.uniqueDomains ?? 0,\n links: payload.links ?? [],\n };\n },\n []\n );\n\n return useWebsiteExtractorBase<WebsiteLinksResponse, WebsiteLinksPayload>({\n endpoint: \"links\",\n options,\n selectData,\n });\n}\n","import { useCallback } from \"react\";\nimport { useWebsiteExtractorBase } from \"./useWebsiteExtractorBase.js\";\nimport type {\n WebsiteExtractorOptions,\n WebsiteExtractorResponse,\n WebsiteExtractorResult,\n WebsiteExtractMeta,\n} from \"./websiteExtractorTypes.js\";\n\nexport interface WebsiteMetaPayload {\n title?: string | null;\n description?: string | null;\n language?: string | null;\n canonicalUrl?: string | null;\n feedUrl?: string | null;\n textContentLength?: number | null;\n metaTags: Record<string, string>;\n}\n\nexport type WebsiteMetaResponse = WebsiteExtractorResponse<WebsiteMetaPayload>;\n\nexport function useWebsiteMetaExtractor(\n options: WebsiteExtractorOptions\n): WebsiteExtractorResult<WebsiteMetaPayload, WebsiteMetaResponse> {\n const selectData = useCallback(\n (\n payload: Omit<WebsiteMetaResponse, keyof WebsiteExtractMeta>\n ): WebsiteMetaPayload => {\n return {\n title: payload.title ?? undefined,\n description: payload.description ?? undefined,\n language: payload.language ?? undefined,\n canonicalUrl: payload.canonicalUrl ?? undefined,\n feedUrl: payload.feedUrl ?? null,\n textContentLength: payload.textContentLength ?? undefined,\n metaTags: payload.metaTags ?? {},\n };\n },\n []\n );\n\n return useWebsiteExtractorBase<WebsiteMetaResponse, WebsiteMetaPayload>({\n endpoint: \"meta\",\n options,\n selectData,\n });\n}\n","import { useCallback } from \"react\";\nimport { useWebsiteExtractorBase } from \"./useWebsiteExtractorBase.js\";\nimport type {\n WebsiteExtractorOptions,\n WebsiteExtractorResponse,\n WebsiteExtractorResult,\n WebsiteExtractMeta,\n} from \"./websiteExtractorTypes.js\";\n\nexport interface WebsiteRssFeed {\n url: string;\n feedType: string;\n title?: string | null;\n}\n\nexport interface WebsiteRssPayload {\n feedUrl?: string | null;\n feeds: WebsiteRssFeed[];\n}\n\nexport type WebsiteRssResponse = WebsiteExtractorResponse<WebsiteRssPayload>;\n\nexport function useWebsiteRssExtractor(\n options: WebsiteExtractorOptions\n): WebsiteExtractorResult<WebsiteRssPayload, WebsiteRssResponse> {\n const selectData = useCallback(\n (\n payload: Omit<WebsiteRssResponse, keyof WebsiteExtractMeta>\n ): WebsiteRssPayload => {\n return {\n feedUrl: payload.feedUrl ?? null,\n feeds: payload.feeds ?? [],\n };\n },\n []\n );\n\n return useWebsiteExtractorBase<WebsiteRssResponse, WebsiteRssPayload>({\n endpoint: \"rss\",\n options,\n selectData,\n });\n}\n","import { useCallback } from \"react\";\nimport { useWebsiteExtractorBase } from \"./useWebsiteExtractorBase.js\";\nimport type {\n WebsiteExtractorOptions,\n WebsiteExtractorResponse,\n WebsiteExtractorResult,\n WebsiteExtractMeta,\n} from \"./websiteExtractorTypes.js\";\n\nexport interface WebsiteSchemaRecord {\n schema_type: string;\n value: Record<string, unknown>;\n}\n\nexport interface WebsiteSchemaPayload {\n schema: WebsiteSchemaRecord[];\n schemaTypes: string[];\n}\n\nexport type WebsiteSchemaResponse = WebsiteExtractorResponse<WebsiteSchemaPayload>;\n\nexport function useWebsiteSchemaExtractor(\n options: WebsiteExtractorOptions\n): WebsiteExtractorResult<WebsiteSchemaPayload, WebsiteSchemaResponse> {\n const selectData = useCallback(\n (\n payload: Omit<WebsiteSchemaResponse, keyof WebsiteExtractMeta>\n ): WebsiteSchemaPayload => {\n return {\n schema: payload.schema ?? [],\n schemaTypes: payload.schemaTypes ?? [],\n };\n },\n []\n );\n\n return useWebsiteExtractorBase<WebsiteSchemaResponse, WebsiteSchemaPayload>({\n endpoint: \"schema\",\n options,\n selectData,\n });\n}\n"],"names":["useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","useDebounceCallback","callback","delay","options","callbackRef","useRef","timeoutRef","maxTimeoutRef","lastArgsRef","leading","trailing","maxWait","wait","Math","max","current","clearTimers","useCallback","clearTimeout","invoke","args","debouncedCallback","setTimeout","maxDelay","cancel","flush","useDebounceValue","value","debouncedValue","setDebouncedValue","useState","next","useEventListener","eventName","handler","element","savedHandler","isWindow","Window","isDocument","Document","target","HTMLElement","addEventListener","listener","event","currentHandler","handleEvent","removeEventListener","useIsClient","isClient","setIsClient","useMap","initialState","map","setMap","Map","Array","isArray","mapRef","actions","useMemo","set","key","prev","setAll","entries","remove","delete","clear","get","has","DEFAULT_WEBSITE_EXTRACTOR_BASE_URL","buildWebsiteExtractorUrl","request","baseUrl","replace","normalizeBaseUrl","params","URLSearchParams","apiKey","url","endpoint","toString","async","fetchWebsiteExtractor","trim","length","ok","error","message","response","fetch","method","signal","payload","json","errorPayload","status","raw","_a","aborted","Error","useWebsiteExtractorBase","config","selectData","shouldSkip","state","setState","loading","cacheActions","cacheEnabled","cache","enabled","debounceMs","refreshDebounceMs","debouncedUrl","refreshCounterRef","lastRefreshHandledRef","refreshToken","setRefreshToken","scheduleRefresh","cancelRefresh","refresh","requestKey","inFlightControllerRef","forceRefresh","cached","data","meta","abort","controller","AbortController","then","result","requestedUrl","finalUrl","normalizedUrl","contentType","fetchedAt","bodyBytes","bodyTruncated","maxBodyBytes","extractWebsiteMeta","_requestedUrl","_finalUrl","_url","_normalizedUrl","_status","_contentType","_fetchedAt","_bodyBytes","_bodyTruncated","_maxBodyBytes","_cache","stripWebsiteMeta","catch","DEFAULT_SKIP_PATTERNS","pickFirstString","values","safeHost","URL","hostname","defaultValue","setValue","setTrue","setFalse","toggle","resetDelay","copiedText","setCopiedText","isSupported","navigator","clipboard","document","queryCommandSupported","resetCopied","copy","text","shouldUseClipboardApi","writeText","textarea","createElement","setAttribute","style","position","left","top","body","appendChild","focus","select","success","execCommand","removeChild","ref","isHovered","setIsHovered","handleEnter","handleLeave","initialValue","initializeWithValue","serialize","JSON","stringify","deserialize","parse","listenToStorageChanges","initialValueRef","readValue","item","localStorage","getItem","storedValue","setStoredValue","valueToStore","setItem","handleStorageChange","newValue","query","matches","setMatches","matchMedia","mediaQueryList","addListener","removeListener","eventType","handlerRef","refs","Node","some","currentRef","node","contains","skipPatterns","pattern","test","_raw","openGraph","htmlInferred","hybridGraph","description","title","siteName","site_name","favicon","image","_b","images","video","_c","videoType","resolvedUrl","siteHost","onResize","entryRef","entry","setEntry","ResizeObserver","Element","observer","firstEntry","observe","disconnect","sessionStorage","interval","throttledValue","setThrottledValue","lastExecutedRef","pendingValueRef","now","Date","elapsed","remaining","totalLinks","uniqueDomains","links","language","canonicalUrl","feedUrl","textContentLength","metaTags","feeds","schema","schemaTypes"],"mappings":"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"}
@@ -14,3 +14,10 @@ export { useResizeObserver } from "./useResizeObserver.js";
14
14
  export { useHover } from "./useHover.js";
15
15
  export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
16
16
  export { useMap } from "./useMap.js";
17
+ export { useOpenGraphExtractor } from "./useOpenGraphExtractor.js";
18
+ export { useWebsiteSchemaExtractor } from "./useWebsiteSchemaExtractor.js";
19
+ export { useWebsiteLinksExtractor } from "./useWebsiteLinksExtractor.js";
20
+ export { useWebsiteMetaExtractor } from "./useWebsiteMetaExtractor.js";
21
+ export { useWebsiteRssExtractor } from "./useWebsiteRssExtractor.js";
22
+ export { fetchWebsiteExtractor } from "./websiteExtractorService.js";
23
+ export { buildWebsiteExtractorUrl } from "./websiteExtractorService.js";
@@ -22,3 +22,16 @@ export { useHover } from "./useHover.js";
22
22
  export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
23
23
  export { useMap } from "./useMap.js";
24
24
  export type { MapActions } from "./useMap.js";
25
+ export { useOpenGraphExtractor } from "./useOpenGraphExtractor.js";
26
+ export type { OpenGraphData, OpenGraphExtractorOptions, OpenGraphHtmlInferredData, OpenGraphHybridData, OpenGraphImage, OpenGraphResponse, OpenGraphSummary, OpenGraphVideo, } from "./useOpenGraphExtractor.js";
27
+ export { useWebsiteSchemaExtractor } from "./useWebsiteSchemaExtractor.js";
28
+ export type { WebsiteSchemaPayload, WebsiteSchemaRecord, WebsiteSchemaResponse, } from "./useWebsiteSchemaExtractor.js";
29
+ export { useWebsiteLinksExtractor } from "./useWebsiteLinksExtractor.js";
30
+ export type { WebsiteLinkRecord, WebsiteLinksPayload, WebsiteLinksResponse, } from "./useWebsiteLinksExtractor.js";
31
+ export { useWebsiteMetaExtractor } from "./useWebsiteMetaExtractor.js";
32
+ export type { WebsiteMetaPayload, WebsiteMetaResponse, } from "./useWebsiteMetaExtractor.js";
33
+ export { useWebsiteRssExtractor } from "./useWebsiteRssExtractor.js";
34
+ export type { WebsiteRssFeed, WebsiteRssPayload, WebsiteRssResponse, } from "./useWebsiteRssExtractor.js";
35
+ export { fetchWebsiteExtractor } from "./websiteExtractorService.js";
36
+ export { buildWebsiteExtractorUrl } from "./websiteExtractorService.js";
37
+ export type { WebsiteExtractCacheMeta, WebsiteExtractMeta, WebsiteExtractorError, WebsiteExtractorOptions, WebsiteExtractorRequest, WebsiteExtractorResponse, WebsiteExtractorResult, WebsiteExtractorState, } from "./websiteExtractorTypes.js";
@@ -14,3 +14,10 @@ export { useResizeObserver } from "./useResizeObserver.js";
14
14
  export { useHover } from "./useHover.js";
15
15
  export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
16
16
  export { useMap } from "./useMap.js";
17
+ export { useOpenGraphExtractor } from "./useOpenGraphExtractor.js";
18
+ export { useWebsiteSchemaExtractor } from "./useWebsiteSchemaExtractor.js";
19
+ export { useWebsiteLinksExtractor } from "./useWebsiteLinksExtractor.js";
20
+ export { useWebsiteMetaExtractor } from "./useWebsiteMetaExtractor.js";
21
+ export { useWebsiteRssExtractor } from "./useWebsiteRssExtractor.js";
22
+ export { fetchWebsiteExtractor } from "./websiteExtractorService.js";
23
+ export { buildWebsiteExtractorUrl } from "./websiteExtractorService.js";
@@ -0,0 +1,59 @@
1
+ import { useCallback, useMemo } from "react";
2
+ import { useWebsiteExtractorBase } from "./useWebsiteExtractorBase.js";
3
+ const DEFAULT_SKIP_PATTERNS = [
4
+ /search\.google\.com\/local\/reviews/i,
5
+ /google\.com\/maps\/place/i,
6
+ /maps\.google\.com/i,
7
+ /opentable\.com/i,
8
+ ];
9
+ const pickFirstString = (...values) => {
10
+ for (const value of values) {
11
+ if (typeof value === "string" && value.trim().length > 0) {
12
+ return value;
13
+ }
14
+ }
15
+ return undefined;
16
+ };
17
+ const safeHost = (value) => {
18
+ if (!value) {
19
+ return undefined;
20
+ }
21
+ try {
22
+ return new URL(value).hostname;
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ };
28
+ export function useOpenGraphExtractor(options) {
29
+ const skipPatterns = useMemo(() => options.skipPatterns ?? DEFAULT_SKIP_PATTERNS, [options.skipPatterns]);
30
+ const shouldSkip = useCallback((url) => skipPatterns.some((pattern) => pattern.test(url)), [skipPatterns]);
31
+ const selectData = useCallback((payload, _raw, meta) => {
32
+ const { openGraph, htmlInferred, hybridGraph } = payload;
33
+ const description = pickFirstString(openGraph?.description, hybridGraph?.description, htmlInferred?.description);
34
+ const title = pickFirstString(openGraph?.title, hybridGraph?.title, htmlInferred?.title);
35
+ const siteName = pickFirstString(openGraph?.site_name, hybridGraph?.site_name, htmlInferred?.site_name);
36
+ const favicon = pickFirstString(hybridGraph?.favicon, htmlInferred?.favicon);
37
+ const image = pickFirstString(openGraph?.image?.url ?? undefined, hybridGraph?.image ?? undefined, htmlInferred?.image ?? undefined, htmlInferred?.images?.[0]);
38
+ const video = pickFirstString(openGraph?.video?.url ?? undefined, hybridGraph?.video ?? undefined);
39
+ const videoType = pickFirstString(hybridGraph?.videoType, htmlInferred?.videoType);
40
+ const resolvedUrl = pickFirstString(meta.url, openGraph?.url ?? undefined, hybridGraph?.url ?? undefined, htmlInferred?.url ?? undefined, meta.finalUrl, meta.normalizedUrl, meta.requestedUrl) ?? "";
41
+ return {
42
+ description,
43
+ favicon,
44
+ image,
45
+ video,
46
+ videoType,
47
+ siteName,
48
+ title,
49
+ url: resolvedUrl,
50
+ siteHost: safeHost(resolvedUrl),
51
+ };
52
+ }, []);
53
+ return useWebsiteExtractorBase({
54
+ endpoint: "open-graph",
55
+ options,
56
+ selectData,
57
+ shouldSkip,
58
+ });
59
+ }
@@ -0,0 +1,64 @@
1
+ import type { WebsiteExtractorOptions, WebsiteExtractorResponse, WebsiteExtractorResult } from "./websiteExtractorTypes.js";
2
+ export interface OpenGraphImage {
3
+ url?: string | null;
4
+ height?: string | null;
5
+ width?: string | null;
6
+ }
7
+ export interface OpenGraphVideo {
8
+ url?: string | null;
9
+ height?: string | null;
10
+ width?: string | null;
11
+ }
12
+ export interface OpenGraphData {
13
+ description?: string | null;
14
+ title?: string | null;
15
+ site_name?: string | null;
16
+ image?: OpenGraphImage | null;
17
+ video?: OpenGraphVideo | null;
18
+ url?: string | null;
19
+ ogType?: string | null;
20
+ }
21
+ export interface OpenGraphHtmlInferredData {
22
+ description?: string | null;
23
+ title?: string | null;
24
+ type?: string | null;
25
+ videoType?: string | null;
26
+ url?: string | null;
27
+ favicon?: string | null;
28
+ images?: string[] | null;
29
+ image?: string | null;
30
+ site_name?: string | null;
31
+ }
32
+ export interface OpenGraphHybridData {
33
+ description?: string | null;
34
+ title?: string | null;
35
+ type?: string | null;
36
+ image?: string | null;
37
+ video?: string | null;
38
+ videoType?: string | null;
39
+ favicon?: string | null;
40
+ site_name?: string | null;
41
+ url?: string | null;
42
+ videoWidth?: number | null;
43
+ videoHeight?: number | null;
44
+ }
45
+ export type OpenGraphResponse = WebsiteExtractorResponse<{
46
+ openGraph: OpenGraphData;
47
+ htmlInferred: OpenGraphHtmlInferredData;
48
+ hybridGraph: OpenGraphHybridData;
49
+ }>;
50
+ export interface OpenGraphSummary {
51
+ description?: string;
52
+ favicon?: string;
53
+ image?: string;
54
+ video?: string;
55
+ videoType?: string;
56
+ siteName?: string;
57
+ title?: string;
58
+ url: string;
59
+ siteHost?: string;
60
+ }
61
+ export interface OpenGraphExtractorOptions extends WebsiteExtractorOptions {
62
+ skipPatterns?: RegExp[];
63
+ }
64
+ export declare function useOpenGraphExtractor(options: OpenGraphExtractorOptions): WebsiteExtractorResult<OpenGraphSummary, OpenGraphResponse>;
@@ -0,0 +1,59 @@
1
+ import { useCallback, useMemo } from "react";
2
+ import { useWebsiteExtractorBase } from "./useWebsiteExtractorBase.js";
3
+ const DEFAULT_SKIP_PATTERNS = [
4
+ /search\.google\.com\/local\/reviews/i,
5
+ /google\.com\/maps\/place/i,
6
+ /maps\.google\.com/i,
7
+ /opentable\.com/i,
8
+ ];
9
+ const pickFirstString = (...values) => {
10
+ for (const value of values) {
11
+ if (typeof value === "string" && value.trim().length > 0) {
12
+ return value;
13
+ }
14
+ }
15
+ return undefined;
16
+ };
17
+ const safeHost = (value) => {
18
+ if (!value) {
19
+ return undefined;
20
+ }
21
+ try {
22
+ return new URL(value).hostname;
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ };
28
+ export function useOpenGraphExtractor(options) {
29
+ const skipPatterns = useMemo(() => options.skipPatterns ?? DEFAULT_SKIP_PATTERNS, [options.skipPatterns]);
30
+ const shouldSkip = useCallback((url) => skipPatterns.some((pattern) => pattern.test(url)), [skipPatterns]);
31
+ const selectData = useCallback((payload, _raw, meta) => {
32
+ const { openGraph, htmlInferred, hybridGraph } = payload;
33
+ const description = pickFirstString(openGraph?.description, hybridGraph?.description, htmlInferred?.description);
34
+ const title = pickFirstString(openGraph?.title, hybridGraph?.title, htmlInferred?.title);
35
+ const siteName = pickFirstString(openGraph?.site_name, hybridGraph?.site_name, htmlInferred?.site_name);
36
+ const favicon = pickFirstString(hybridGraph?.favicon, htmlInferred?.favicon);
37
+ const image = pickFirstString(openGraph?.image?.url ?? undefined, hybridGraph?.image ?? undefined, htmlInferred?.image ?? undefined, htmlInferred?.images?.[0]);
38
+ const video = pickFirstString(openGraph?.video?.url ?? undefined, hybridGraph?.video ?? undefined);
39
+ const videoType = pickFirstString(hybridGraph?.videoType, htmlInferred?.videoType);
40
+ const resolvedUrl = pickFirstString(meta.url, openGraph?.url ?? undefined, hybridGraph?.url ?? undefined, htmlInferred?.url ?? undefined, meta.finalUrl, meta.normalizedUrl, meta.requestedUrl) ?? "";
41
+ return {
42
+ description,
43
+ favicon,
44
+ image,
45
+ video,
46
+ videoType,
47
+ siteName,
48
+ title,
49
+ url: resolvedUrl,
50
+ siteHost: safeHost(resolvedUrl),
51
+ };
52
+ }, []);
53
+ return useWebsiteExtractorBase({
54
+ endpoint: "open-graph",
55
+ options,
56
+ selectData,
57
+ shouldSkip,
58
+ });
59
+ }