preact-missing-hooks 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +1 -0
- package/.husky/pre-push +1 -0
- package/.prettierignore +3 -0
- package/.prettierrc +6 -0
- package/Readme.md +149 -136
- package/dist/entry.cjs +21 -0
- package/dist/entry.js +2 -0
- package/dist/entry.js.map +1 -0
- package/dist/entry.modern.mjs +2 -0
- package/dist/entry.modern.mjs.map +1 -0
- package/dist/entry.module.js +2 -0
- package/dist/entry.module.js.map +1 -0
- package/dist/entry.umd.js +2 -0
- package/dist/entry.umd.js.map +1 -0
- package/dist/index.d.ts +13 -13
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +2 -0
- package/dist/index.modern.mjs.map +1 -0
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/indexedDB/dbController.d.ts +2 -2
- package/dist/indexedDB/index.d.ts +6 -6
- package/dist/indexedDB/openDB.d.ts +1 -1
- package/dist/indexedDB/tableController.d.ts +1 -1
- package/dist/indexedDB/types.d.ts +1 -2
- package/dist/react.js +1 -0
- package/dist/react.modern.mjs +1 -0
- package/dist/react.module.js +1 -0
- package/dist/react.umd.js +1 -0
- package/dist/useEventBus.d.ts +1 -1
- package/dist/useIndexedDB.d.ts +3 -3
- package/dist/useMutationObserver.d.ts +1 -1
- package/dist/useNetworkState.d.ts +3 -3
- package/dist/usePreferredTheme.d.ts +1 -1
- package/dist/useRageClick.d.ts +1 -1
- package/dist/useThreadedWorker.d.ts +1 -1
- package/dist/useTransition.d.ts +4 -1
- package/dist/useWorkerNotifications.d.ts +1 -1
- package/dist/useWrappedChildren.d.ts +3 -3
- package/eslint.config.mjs +10 -0
- package/package.json +60 -6
- package/scripts/generate-entry.cjs +34 -0
- package/src/index.ts +13 -13
- package/src/indexedDB/dbController.ts +101 -92
- package/src/indexedDB/index.ts +16 -11
- package/src/indexedDB/openDB.ts +49 -49
- package/src/indexedDB/requestToPromise.ts +17 -16
- package/src/indexedDB/tableController.ts +331 -257
- package/src/indexedDB/types.ts +35 -35
- package/src/useClipboard.ts +99 -97
- package/src/useEventBus.ts +39 -36
- package/src/useIndexedDB.ts +111 -111
- package/src/useMutationObserver.ts +26 -26
- package/src/useNetworkState.ts +124 -122
- package/src/usePreferredTheme.ts +68 -68
- package/src/useRageClick.ts +103 -103
- package/src/useThreadedWorker.ts +165 -165
- package/src/useTransition.ts +22 -19
- package/src/useWasmCompute.ts +209 -204
- package/src/useWebRTCIP.ts +181 -176
- package/src/useWorkerNotifications.ts +28 -20
- package/src/useWrappedChildren.ts +72 -58
- package/tests/react-adapter.tsx +12 -0
- package/tests/setup-react.ts +4 -0
- package/tests/useClipboard.test.tsx +4 -2
- package/tests/useThreadedWorker.test.tsx +3 -1
- package/tests/useWasmCompute.test.tsx +1 -1
- package/tests/useWebRTCIP.test.tsx +3 -1
- package/vite.config.ts +11 -4
- package/vitest.config.preact.ts +20 -0
- package/vitest.config.react.ts +36 -0
- package/vitest.workspace.ts +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useState as e,useCallback as r,useEffect as n,useMemo as t,useRef as o}from"react/hooks";import{isValidElement as s,cloneElement as i}from"react";function c(){const[n,t]=e(!1);return[r(e=>{t(!0),Promise.resolve().then(()=>{e(),t(!1)})},[]),n]}function u(e,r,t){n(()=>{const n=e.current;if(!n)return;const o=new MutationObserver(r);return o.observe(n,t),()=>o.disconnect()},[e,r,t])}const a=new Map;function l(){return{emit:r((e,...r)=>{const n=a.get(e);n&&n.forEach(e=>e(...r))},[]),on:r((e,r)=>{let n=a.get(e);return n||(n=new Set,a.set(e,n)),n.add(r),()=>{n.delete(r),0===n.size&&a.delete(e)}},[])}}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var t in n)({}).hasOwnProperty.call(n,t)&&(e[t]=n[t])}return e},d.apply(null,arguments)}function f(e,r,n="preserve"){return t(()=>{if(!e)return e;const t=e=>{if(!s(e))return e;const t=e.props||{};let o;o="override"===n?d({},t,r):d({},r,t);const c=null==t?void 0:t.style,u=null==r?void 0:r.style;return c&&u&&"object"==typeof c&&"object"==typeof u&&(o.style="override"===n?d({},c,u):d({},u,c)),i(e,o)};return Array.isArray(e)?e.map(t):t(e)},[e,r,n])}function p(){const[r,t]=e(()=>{if("undefined"==typeof window)return"no-preference";const e=window.matchMedia("(prefers-color-scheme: dark)"),r=window.matchMedia("(prefers-color-scheme: light)");return e.matches?"dark":r.matches?"light":"no-preference"});return n(()=>{if("undefined"==typeof window)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=e=>{t(e.matches?"dark":"light")},n=()=>{const e=window.matchMedia("(prefers-color-scheme: dark)"),r=window.matchMedia("(prefers-color-scheme: light)");t(e.matches?"dark":r.matches?"light":"no-preference")};e.addEventListener("change",r);const o=window.matchMedia("(prefers-color-scheme: light)");return o.addEventListener("change",n),()=>{e.removeEventListener("change",r),o.removeEventListener("change",n)}},[]),r}function v(){if("undefined"==typeof navigator)return{online:!0};const e={online:navigator.onLine},r=navigator.connection;return r&&(void 0!==r.effectiveType&&(e.effectiveType=r.effectiveType),void 0!==r.downlink&&(e.downlink=r.downlink),void 0!==r.rtt&&(e.rtt=r.rtt),void 0!==r.saveData&&(e.saveData=r.saveData),void 0!==r.type&&(e.connectionType=r.type)),e}function m(){const[r,t]=e(v);return n(()=>{if("undefined"==typeof window)return;const e=()=>t(v());window.addEventListener("online",e),window.addEventListener("offline",e);const r=navigator.connection;return null!=r&&r.addEventListener&&r.addEventListener("change",e),()=>{window.removeEventListener("online",e),window.removeEventListener("offline",e),null!=r&&r.removeEventListener&&r.removeEventListener("change",e)}},[]),r}function h(n={}){const{resetDelay:t=2e3}=n,[o,s]=e(!1),[i,c]=e(null),u=r(()=>{s(!1),c(null)},[]);return{copy:r(async e=>{if(c(null),"undefined"==typeof navigator||!navigator.clipboard){const e=new Error("Clipboard API is not available");return c(e),!1}try{return await navigator.clipboard.writeText(e),s(!0),t>0&&setTimeout(()=>s(!1),t),!0}catch(e){const r=e instanceof Error?e:new Error(String(e));return c(r),!1}},[t]),paste:r(async()=>{if(c(null),"undefined"==typeof navigator||!navigator.clipboard){const e=new Error("Clipboard API is not available");return c(e),""}try{return await navigator.clipboard.readText()}catch(e){const r=e instanceof Error?e:new Error(String(e));return c(r),""}},[]),copied:o,error:i,reset:u}}function w(e,r){const{onRageClick:t,threshold:s=5,timeWindow:i=1e3,distanceThreshold:c=30}=r,u=o(t);u.current=t;const a=o([]);n(()=>{const r=e.current;if(!r)return;const n=e=>{const r=Date.now(),n={time:r,x:e.clientX,y:e.clientY},t=r-i,o=a.current.filter(e=>e.time>=t);if(o.push(n),Infinity!==c){const r=o.filter(e=>{return r=e,t=n,Math.hypot(t.x-r.x,t.y-r.y)<=c;var r,t});if(r.length>=s)return u.current({count:r.length,event:e}),void(a.current=[])}else if(o.length>=s)return u.current({count:o.length,event:e}),void(a.current=[]);a.current=o};return r.addEventListener("click",n),()=>r.removeEventListener("click",n)},[e,s,i,c])}function y(t,s){const{mode:i,concurrency:c=4}=s,u="sequential"===i?1:Math.max(1,c),[a,l]=e(!1),[d,f]=e(void 0),[p,v]=e(void 0),[m,h]=e(0),w=o([]),y=o(0),g=o(0),b=o(!1),E=o(t);E.current=t;const k=r(()=>{h(w.current.length+g.current)},[]),x=r(()=>{if(b.current)return;if(g.current>=u)return;if(0===w.current.length)return 0===g.current&&l(!1),void k();w.current.sort((e,r)=>e.priority!==r.priority?e.priority-r.priority:e.sequence-r.sequence);const e=w.current.shift();g.current+=1,l(!0),k(),(0,E.current)(e.data).then(r=>{f(r),v(void 0),e.resolve(r)}).catch(r=>{v(r),e.reject(r)}).finally(()=>{g.current-=1,k(),x()}),w.current.length>0&&g.current<u&&x()},[u,k]),M=r((e,r)=>{var n;if(b.current)return Promise.reject(new Error("Worker is terminated"));const t=null!=(n=null==r?void 0:r.priority)?n:1,o=++y.current,s=new Promise((r,n)=>{w.current.push({data:e,priority:t,sequence:o,resolve:r,reject:n})});return k(),l(!0),queueMicrotask(x),s},[x,k]),S=r(()=>{const e=w.current;w.current=[],e.forEach(e=>e.reject(new Error("Task cleared from queue"))),k(),0===g.current&&l(!1)},[k]),P=r(()=>{b.current=!0,S()},[S]);return n(()=>()=>{b.current=!0},[]),{run:M,loading:a,result:d,error:p,queueSize:m,clearQueue:S,terminate:P}}const g=new Map;function b(e){return new Promise((r,n)=>{e.onsuccess=()=>r(e.result),e.onerror=()=>{var r;return n(null!=(r=e.error)?r:new DOMException("Unknown IndexedDB error"))}})}function E(e,r){return r?e.then(e=>(null==r.onSuccess||r.onSuccess(e),e)).catch(e=>{throw null==r.onError||r.onError(e),e}):e}function k(r){const[t,s]=e(null),[i,c]=e(null),[u,a]=e(!1),l=o(r);return l.current=r,n(()=>{let e=!1;c(null),a(!1),s(null);const{name:r,version:n,tables:t}=l.current;return function(e){const r=`${e.name}_v${e.version}`;let n=g.get(r);return n||(n=function(e){return new Promise((r,n)=>{const t=indexedDB.open(e.name,e.version);t.onerror=()=>{var e;return n(null!=(e=t.error)?e:new DOMException("Failed to open database"))},t.onsuccess=()=>r(t.result),t.onupgradeneeded=r=>{const n=r.target.result,t=e.tables;for(const e of Object.keys(t)){const r=t[e];if(!n.objectStoreNames.contains(e)){var o;const t=n.createObjectStore(e,{keyPath:r.keyPath,autoIncrement:null!=(o=r.autoIncrement)&&o});if(r.indexes)for(const e of r.indexes)t.createIndex(e,e,{unique:!1})}}}})}(e),g.set(r,n),n)}({name:r,version:n,tables:t}).then(r=>{if(e)return void r.close();const n=function(e){return{get db(){return e},hasTable:r=>e.objectStoreNames.contains(r),table:r=>function(e,r){return function(e,r){function n(n){return e.transaction([r],n).objectStore(r)}return{insert:(e,r)=>E(b(n("readwrite").add(e)),r),update(e,r,t){const o=n("readwrite");return E(b(o.get(e)).then(e=>{if(void 0===e)throw new DOMException("Key not found","NotFoundError");const n=d({},e,r);return b(o.put(n))}).then(()=>{}),t)},delete:(e,r)=>E(b(n("readwrite").delete(e)).then(()=>{}),r),exists:e=>b(n("readonly").getKey(e)).then(e=>void 0!==e),query(e,r){const t=n("readonly").openCursor(),o=[];return E(new Promise((r,n)=>{t.onsuccess=()=>{const n=t.result;n?(e(n.value)&&o.push(n.value),n.continue()):r(o)},t.onerror=()=>{var e;return n(null!=(e=t.error)?e:new DOMException("Unknown error"))}}),r)},upsert:(e,r)=>E(b(n("readwrite").put(e)),r),bulkInsert(e,r){const t=n("readwrite"),o=[];if(0===e.length)return E(Promise.resolve(o),r);let s=0;return E(new Promise((r,n)=>{e.forEach((i,c)=>{const u=t.add(i);u.onsuccess=()=>{o[c]=u.result,s++,s===e.length&&r(o)},u.onerror=()=>{var e;return n(null!=(e=u.error)?e:new DOMException("Unknown error"))}})}),r)},clear:e=>E(b(n("readwrite").clear()).then(()=>{}),e),count:e=>E(b(n("readonly").count()),null!=e?e:{})}}(e,r)}(e,r),transaction(r,n,t,o){const s=e.transaction(r,n),i={table:e=>function(e,r){return function(e,r){function n(){return e.objectStore(r)}return{insert:(e,r)=>E(b(n().add(e)),r),update(e,r,t){const o=n();return E(b(o.get(e)).then(e=>{if(void 0===e)throw new DOMException("Key not found","NotFoundError");const n=d({},e,r);return b(o.put(n))}).then(()=>{}),t)},delete:(e,r)=>E(b(n().delete(e)).then(()=>{}),r),exists:e=>b(n().getKey(e)).then(e=>void 0!==e),query(e,r){const t=n().openCursor(),o=[];return E(new Promise((r,n)=>{t.onsuccess=()=>{const n=t.result;n?(e(n.value)&&o.push(n.value),n.continue()):r(o)},t.onerror=()=>{var e;return n(null!=(e=t.error)?e:new DOMException("Unknown error"))}}),r)},upsert:(e,r)=>E(b(n().put(e)),r),bulkInsert(e,r){const t=n(),o=[];if(0===e.length)return E(Promise.resolve(o),r);let s=0;return E(new Promise((r,n)=>{e.forEach((i,c)=>{const u=t.add(i);u.onsuccess=()=>{o[c]=u.result,s++,s===e.length&&r(o)},u.onerror=()=>{var e;return n(null!=(e=u.error)?e:new DOMException("Unknown error"))}})}),r)},clear:e=>E(b(n().clear()).then(()=>{}),e),count:e=>E(b(n().count()),null!=e?e:{})}}(e,r)}(s,e)},c=new Promise((e,r)=>{s.oncomplete=()=>e(),s.onerror=()=>{var e;return r(null!=(e=s.error)?e:new DOMException("Transaction failed"))}}),u=t(i);return function(e,r){return r?e.then(()=>null==r.onSuccess?void 0:r.onSuccess()).catch(e=>{throw null==r.onError||r.onError(e),e}):e}(Promise.resolve(u).then(()=>c),o)}}}(r);s(n),a(!0)}).catch(r=>{e||c(r)}),()=>{e=!0}},[r.name,r.version]),{db:t,isReady:u,error:i}}const x=/\b(?:25[0-5]|2[0-4]\d|1?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|1?\d{1,2})){3}\b/g,M=["stun:stun.l.google.com:19302"],S=3e3;function P(r={}){const{stunServers:t=M,timeout:s=S,onDetect:i}=r,[c,u]=e([]),[a,l]=e(!0),[d,f]=e(null),p=o(null),v=o(null),m=o(new Set),h=o(i);return h.current=i,n(()=>{if("undefined"==typeof window)return l(!1),void f("WebRTC IP detection is not available during SSR");if("undefined"==typeof RTCPeerConnection)return l(!1),void f("RTCPeerConnection is not available");const e=new Set;m.current=e;const r=()=>{v.current&&(clearTimeout(v.current),v.current=null),p.current&&(p.current.close(),p.current=null),l(!1)},n=r=>{e.has(r)||(e.add(r),u(e=>[...e,r]),null==h.current||h.current(r))};try{const e=new RTCPeerConnection({iceServers:[{urls:t}]});p.current=e,e.onicecandidate=e=>{const r=e.candidate;r&&r.candidate&&function(e){const r=e.match(x);return r?[...r]:[]}(r.candidate).forEach(n)},e.createDataChannel(""),e.createOffer().then(r=>e.setLocalDescription(r)).catch(e=>{f(e instanceof Error?e.message:"Failed to create offer"),r()}),v.current=setTimeout(()=>r(),s)}catch(e){f(e instanceof Error?e.message:"WebRTC setup failed"),r()}return()=>{r()}},[t.join(","),s]),{ips:c,loading:a,error:d}}function D(t){const{wasmUrl:s,exportName:i="compute",workerUrl:c,importObject:u}=t,[a,l]=e(void 0),[d,f]=e(!0),[p,v]=e(null),[m,h]=e(!1),w=o(null),y=o(null),g=o(null);return n(()=>{if("undefined"==typeof window)return v("useWasmCompute is not available during SSR"),void f(!1);if("undefined"==typeof Worker)return v("Worker is not supported in this environment"),void f(!1);if("undefined"==typeof WebAssembly||"function"!=typeof WebAssembly.instantiate)return v("WebAssembly is not supported in this environment"),void f(!1);v(null),h(!1);const e=function(e){if(e)return new Worker(e);const r=new Blob(["\nself.onmessage = async (e) => {\n const d = e.data;\n if (d.type === 'init') {\n try {\n const res = await fetch(d.wasmUrl);\n const buf = await res.arrayBuffer();\n const mod = await WebAssembly.instantiate(buf, d.importObject || {});\n self.wasmInstance = mod.instance;\n self.exportName = d.exportName || 'compute';\n self.postMessage({ type: 'ready' });\n } catch (err) {\n self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n }\n return;\n }\n if (d.type === 'compute') {\n try {\n const fn = self.wasmInstance.exports[self.exportName];\n if (typeof fn !== 'function') {\n self.postMessage({ type: 'error', error: 'Export \"' + self.exportName + '\" is not a function' });\n return;\n }\n const result = fn(d.input);\n self.postMessage({ type: 'result', result: result });\n } catch (err) {\n self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n }\n }\n};\n"],{type:"application/javascript"}),n=URL.createObjectURL(r),t=new Worker(n);return URL.revokeObjectURL(n),t}(c);w.current=e;const r=e=>{var r;const{type:n,result:t,error:o}=null!=(r=e.data)?r:{};return"ready"===n?(h(!0),void f(!1)):"error"===n?(v(null!=o?o:"Unknown error"),f(!1),void(g.current&&(g.current(new Error(o)),y.current=null,g.current=null))):void("result"===n&&(l(t),f(!1),y.current&&(y.current(t),y.current=null,g.current=null)))};return e.addEventListener("message",r),e.postMessage({type:"init",wasmUrl:s,exportName:i,importObject:null!=u?u:{}}),()=>{e.removeEventListener("message",r),e.terminate(),w.current=null,g.current&&(g.current(new Error("Worker terminated")),y.current=null,g.current=null)}},[s,i,c,u]),{compute:r(e=>new Promise((r,n)=>{w.current&&m?p?n(new Error(p)):(y.current=r,g.current=n,f(!0),w.current.postMessage({type:"compute",input:e})):n(new Error("WASM not ready"))}),[m,p]),result:a,loading:d,error:p,ready:m}}function L(r,s={}){const{maxHistory:i=100,throughputWindowMs:c=1e3}=s,[u,a]=e([]),[l,d]=e(0),[f,p]=e(0),[v,m]=e([]),[h,w]=e(0),y=o([]),g=o(0),b=o(0);n(()=>{if(!r)return;const e=e=>{const r=function(e){if(null==e||"object"!=typeof e)return null;const r=e.type;return"task_start"!==r&&"task_end"!==r&&"task_fail"!==r&&"queue_size"!==r?null:{type:r,taskId:"string"==typeof e.taskId?e.taskId:void 0,duration:"number"==typeof e.duration?e.duration:void 0,error:"string"==typeof e.error?e.error:void 0,size:"number"==typeof e.size?e.size:void 0,timestamp:Date.now()}}(e.data);if(r)if(m(e=>[...e,r].slice(-i)),"task_start"===r.type&&r.taskId)a(e=>e.includes(r.taskId)?e:[...e,r.taskId]);else if("task_end"===r.type){r.taskId&&a(e=>e.filter(e=>e!==r.taskId)),d(e=>e+1);const e=Date.now()-c;y.current=[...y.current.filter(r=>r>=e),r.timestamp],"number"==typeof r.duration&&(g.current+=r.duration,b.current+=1)}else"task_fail"===r.type?(r.taskId&&a(e=>e.filter(e=>e!==r.taskId)),p(e=>e+1)):"queue_size"===r.type&&"number"==typeof r.size&&w(r.size)};return r.addEventListener("message",e),()=>r.removeEventListener("message",e)},[r,i]);const E=t(()=>{const e=b.current;return e>0?g.current/e:0},[v]),k=t(()=>{const e=Date.now()-c;return y.current.filter(r=>r>=e).length/(c/1e3)},[v,c]),x=t(()=>({runningTasks:u,completedCount:l,failedCount:f,averageDurationMs:E,throughputPerSecond:k,currentQueueSize:h,totalProcessed:l+f,recentEventCount:v.length}),[u,l,f,E,k,h,v.length]);return{runningTasks:u,completedCount:l,failedCount:f,eventHistory:v,averageDurationMs:E,throughputPerSecond:k,currentQueueSize:h,progress:x}}export{h as useClipboard,l as useEventBus,k as useIndexedDB,u as useMutationObserver,m as useNetworkState,p as usePreferredTheme,w as useRageClick,y as useThreadedWorker,c as useTransition,D as useWasmCompute,P as useWebRTCIP,L as useWorkerNotifications,f as useWrappedChildren};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useState as n,useCallback as e,useEffect as r,useMemo as t,useRef as o}from"react/hooks";import{isValidElement as u,cloneElement as i}from"react";function c(){var r=n(!1),t=r[0],o=r[1];return[e(function(n){o(!0),Promise.resolve().then(function(){n(),o(!1)})},[]),t]}function a(n,e,t){r(function(){var r=n.current;if(r){var o=new MutationObserver(e);return o.observe(r,t),function(){return o.disconnect()}}},[n,e,t])}var s=new Map;function f(){var n=e(function(n){var e=arguments,r=s.get(n);r&&r.forEach(function(n){return n.apply(void 0,[].slice.call(e,1))})},[]);return{emit:n,on:e(function(n,e){var r=s.get(n);return r||(r=new Set,s.set(n,r)),r.add(e),function(){r.delete(e),0===r.size&&s.delete(n)}},[])}}function l(n,e){(null==e||e>n.length)&&(e=n.length);for(var r=0,t=Array(e);r<e;r++)t[r]=n[r];return t}function d(n,e){var r="undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(r)return(r=r.call(n)).next.bind(r);if(Array.isArray(n)||(r=function(n,e){if(n){if("string"==typeof n)return l(n,e);var r={}.toString.call(n).slice(8,-1);return"Object"===r&&n.constructor&&(r=n.constructor.name),"Map"===r||"Set"===r?Array.from(n):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?l(n,e):void 0}}(n))||e&&n&&"number"==typeof n.length){r&&(n=r);var t=0;return function(){return t>=n.length?{done:!0}:{done:!1,value:n[t++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function v(){return v=Object.assign?Object.assign.bind():function(n){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var t in r)({}).hasOwnProperty.call(r,t)&&(n[t]=r[t])}return n},v.apply(null,arguments)}function p(n,e,r){return void 0===r&&(r="preserve"),t(function(){if(!n)return n;var t=function(n){if(!u(n))return n;var t,o=n.props||{};t="override"===r?v({},o,e):v({},e,o);var c=null==o?void 0:o.style,a=null==e?void 0:e.style;return c&&a&&"object"==typeof c&&"object"==typeof a&&(t.style="override"===r?v({},c,a):v({},a,c)),i(n,t)};return Array.isArray(n)?n.map(t):t(n)},[n,e,r])}function m(){var e=n(function(){if("undefined"==typeof window)return"no-preference";var n=window.matchMedia("(prefers-color-scheme: dark)"),e=window.matchMedia("(prefers-color-scheme: light)");return n.matches?"dark":e.matches?"light":"no-preference"}),t=e[0],o=e[1];return r(function(){if("undefined"!=typeof window){var n=window.matchMedia("(prefers-color-scheme: dark)"),e=function(n){o(n.matches?"dark":"light")},r=function(){var n=window.matchMedia("(prefers-color-scheme: dark)"),e=window.matchMedia("(prefers-color-scheme: light)");o(n.matches?"dark":e.matches?"light":"no-preference")};n.addEventListener("change",e);var t=window.matchMedia("(prefers-color-scheme: light)");return t.addEventListener("change",r),function(){n.removeEventListener("change",e),t.removeEventListener("change",r)}}},[]),t}function h(){if("undefined"==typeof navigator)return{online:!0};var n={online:navigator.onLine},e=navigator.connection;return e&&(void 0!==e.effectiveType&&(n.effectiveType=e.effectiveType),void 0!==e.downlink&&(n.downlink=e.downlink),void 0!==e.rtt&&(n.rtt=e.rtt),void 0!==e.saveData&&(n.saveData=e.saveData),void 0!==e.type&&(n.connectionType=e.type)),n}function y(){var e=n(h),t=e[0],o=e[1];return r(function(){if("undefined"!=typeof window){var n=function(){return o(h())};window.addEventListener("online",n),window.addEventListener("offline",n);var e=navigator.connection;return null!=e&&e.addEventListener&&e.addEventListener("change",n),function(){window.removeEventListener("online",n),window.removeEventListener("offline",n),null!=e&&e.removeEventListener&&e.removeEventListener("change",n)}}},[]),t}function w(n,e){try{var r=n()}catch(n){return e(n)}return r&&r.then?r.then(void 0,e):r}function g(r){void 0===r&&(r={});var t=r.resetDelay,o=void 0===t?2e3:t,u=n(!1),i=u[0],c=u[1],a=n(null),s=a[0],f=a[1],l=e(function(){c(!1),f(null)},[]);return{copy:e(function(n){try{if(f(null),"undefined"==typeof navigator||!navigator.clipboard){var e=new Error("Clipboard API is not available");return f(e),Promise.resolve(!1)}return Promise.resolve(w(function(){return Promise.resolve(navigator.clipboard.writeText(n)).then(function(){return c(!0),o>0&&setTimeout(function(){return c(!1)},o),!0})},function(n){var e=n instanceof Error?n:new Error(String(n));return f(e),!1}))}catch(n){return Promise.reject(n)}},[o]),paste:e(function(){try{if(f(null),"undefined"==typeof navigator||!navigator.clipboard){var n=new Error("Clipboard API is not available");return f(n),Promise.resolve("")}return Promise.resolve(w(function(){return Promise.resolve(navigator.clipboard.readText())},function(n){var e=n instanceof Error?n:new Error(String(n));return f(e),""}))}catch(n){return Promise.reject(n)}},[]),copied:i,error:s,reset:l}}function b(n,e){var t=e.onRageClick,u=e.threshold,i=void 0===u?5:u,c=e.timeWindow,a=void 0===c?1e3:c,s=e.distanceThreshold,f=void 0===s?30:s,l=o(t);l.current=t;var d=o([]);r(function(){var e=n.current;if(e){var r=function(n){var e=Date.now(),r={time:e,x:n.clientX,y:n.clientY},t=e-a,o=d.current.filter(function(n){return n.time>=t});if(o.push(r),Infinity!==f){var u=o.filter(function(n){return e=n,t=r,Math.hypot(t.x-e.x,t.y-e.y)<=f;var e,t});if(u.length>=i)return l.current({count:u.length,event:n}),void(d.current=[])}else if(o.length>=i)return l.current({count:o.length,event:n}),void(d.current=[]);d.current=o};return e.addEventListener("click",r),function(){return e.removeEventListener("click",r)}}},[n,i,a,f])}function E(t,u){var i=u.concurrency,c="sequential"===u.mode?1:Math.max(1,void 0===i?4:i),a=n(!1),s=a[0],f=a[1],l=n(void 0),d=l[0],v=l[1],p=n(void 0),m=p[0],h=p[1],y=n(0),w=y[0],g=y[1],b=o([]),E=o(0),k=o(0),P=o(!1),x=o(t);x.current=t;var M=e(function(){g(b.current.length+k.current)},[]),S=e(function(){if(!(P.current||k.current>=c)){if(0===b.current.length)return 0===k.current&&f(!1),void M();b.current.sort(function(n,e){return n.priority!==e.priority?n.priority-e.priority:n.sequence-e.sequence});var n=b.current.shift();k.current+=1,f(!0),M(),(0,x.current)(n.data).then(function(e){v(e),h(void 0),n.resolve(e)}).catch(function(e){h(e),n.reject(e)}).finally(function(){k.current-=1,M(),S()}),b.current.length>0&&k.current<c&&S()}},[c,M]),j=e(function(n,e){var r;if(P.current)return Promise.reject(new Error("Worker is terminated"));var t=null!=(r=null==e?void 0:e.priority)?r:1,o=++E.current,u=new Promise(function(e,r){b.current.push({data:n,priority:t,sequence:o,resolve:e,reject:r})});return M(),f(!0),queueMicrotask(S),u},[S,M]),I=e(function(){var n=b.current;b.current=[],n.forEach(function(n){return n.reject(new Error("Task cleared from queue"))}),M(),0===k.current&&f(!1)},[M]),D=e(function(){P.current=!0,I()},[I]);return r(function(){return function(){P.current=!0}},[]),{run:j,loading:s,result:d,error:m,queueSize:w,clearQueue:I,terminate:D}}var k=new Map;function P(n){return new Promise(function(e,r){n.onsuccess=function(){return e(n.result)},n.onerror=function(){var e;return r(null!=(e=n.error)?e:new DOMException("Unknown IndexedDB error"))}})}function x(n,e){return e?n.then(function(n){return null==e.onSuccess||e.onSuccess(n),n}).catch(function(n){throw null==e.onError||e.onError(n),n}):n}function M(e){var t=n(null),u=t[0],i=t[1],c=n(null),a=c[0],s=c[1],f=n(!1),l=f[0],p=f[1],m=o(e);return m.current=e,r(function(){var n=!1;s(null),p(!1),i(null);var e=m.current;return function(n){var e=n.name+"_v"+n.version,r=k.get(e);return r||(r=function(n){return new Promise(function(e,r){var t=indexedDB.open(n.name,n.version);t.onerror=function(){var n;return r(null!=(n=t.error)?n:new DOMException("Failed to open database"))},t.onsuccess=function(){return e(t.result)},t.onupgradeneeded=function(e){for(var r=e.target.result,t=n.tables,o=0,u=Object.keys(t);o<u.length;o++){var i=u[o],c=t[i];if(!r.objectStoreNames.contains(i)){var a,s=r.createObjectStore(i,{keyPath:c.keyPath,autoIncrement:null!=(a=c.autoIncrement)&&a});if(c.indexes)for(var f,l=d(c.indexes);!(f=l()).done;){var v=f.value;s.createIndex(v,v,{unique:!1})}}}}})}(n),k.set(e,r),r)}({name:e.name,version:e.version,tables:e.tables}).then(function(e){if(n)e.close();else{var r=function(n){return{get db(){return n},hasTable:function(e){return n.objectStoreNames.contains(e)},table:function(e){return function(n,e){return function(n,e){function r(r){return n.transaction([e],r).objectStore(e)}return{insert:function(n,e){return x(P(r("readwrite").add(n)),e)},update:function(n,e,t){var o=r("readwrite");return x(P(o.get(n)).then(function(n){if(void 0===n)throw new DOMException("Key not found","NotFoundError");var r=v({},n,e);return P(o.put(r))}).then(function(){}),t)},delete:function(n,e){return x(P(r("readwrite").delete(n)).then(function(){}),e)},exists:function(n){return P(r("readonly").getKey(n)).then(function(n){return void 0!==n})},query:function(n,e){var t=r("readonly").openCursor(),o=[];return x(new Promise(function(e,r){t.onsuccess=function(){var r=t.result;r?(n(r.value)&&o.push(r.value),r.continue()):e(o)},t.onerror=function(){var n;return r(null!=(n=t.error)?n:new DOMException("Unknown error"))}}),e)},upsert:function(n,e){return x(P(r("readwrite").put(n)),e)},bulkInsert:function(n,e){var t=r("readwrite"),o=[];if(0===n.length)return x(Promise.resolve(o),e);var u=0;return x(new Promise(function(e,r){n.forEach(function(i,c){var a=t.add(i);a.onsuccess=function(){o[c]=a.result,++u===n.length&&e(o)},a.onerror=function(){var n;return r(null!=(n=a.error)?n:new DOMException("Unknown error"))}})}),e)},clear:function(n){return x(P(r("readwrite").clear()).then(function(){}),n)},count:function(n){return x(P(r("readonly").count()),null!=n?n:{})}}}(n,e)}(n,e)},transaction:function(e,r,t,o){var u=n.transaction(e,r),i={table:function(n){return function(n,e){return function(n,e){function r(){return n.objectStore(e)}return{insert:function(n,e){return x(P(r().add(n)),e)},update:function(n,e,t){var o=r();return x(P(o.get(n)).then(function(n){if(void 0===n)throw new DOMException("Key not found","NotFoundError");var r=v({},n,e);return P(o.put(r))}).then(function(){}),t)},delete:function(n,e){return x(P(r().delete(n)).then(function(){}),e)},exists:function(n){return P(r().getKey(n)).then(function(n){return void 0!==n})},query:function(n,e){var t=r().openCursor(),o=[];return x(new Promise(function(e,r){t.onsuccess=function(){var r=t.result;r?(n(r.value)&&o.push(r.value),r.continue()):e(o)},t.onerror=function(){var n;return r(null!=(n=t.error)?n:new DOMException("Unknown error"))}}),e)},upsert:function(n,e){return x(P(r().put(n)),e)},bulkInsert:function(n,e){var t=r(),o=[];if(0===n.length)return x(Promise.resolve(o),e);var u=0;return x(new Promise(function(e,r){n.forEach(function(i,c){var a=t.add(i);a.onsuccess=function(){o[c]=a.result,++u===n.length&&e(o)},a.onerror=function(){var n;return r(null!=(n=a.error)?n:new DOMException("Unknown error"))}})}),e)},clear:function(n){return x(P(r().clear()).then(function(){}),n)},count:function(n){return x(P(r().count()),null!=n?n:{})}}}(n,e)}(u,n)}},c=new Promise(function(n,e){u.oncomplete=function(){return n()},u.onerror=function(){var n;return e(null!=(n=u.error)?n:new DOMException("Transaction failed"))}}),a=t(i);return function(n,e){return e?n.then(function(){return null==e.onSuccess?void 0:e.onSuccess()}).catch(function(n){throw null==e.onError||e.onError(n),n}):n}(Promise.resolve(a).then(function(){return c}),o)}}}(e);i(r),p(!0)}}).catch(function(e){n||s(e)}),function(){n=!0}},[e.name,e.version]),{db:u,isReady:l,error:a}}var S=/\b(?:25[0-5]|2[0-4]\d|1?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|1?\d{1,2})){3}\b/g,j=["stun:stun.l.google.com:19302"];function I(e){void 0===e&&(e={});var t=e.stunServers,u=void 0===t?j:t,i=e.timeout,c=void 0===i?3e3:i,a=e.onDetect,s=n([]),f=s[0],l=s[1],d=n(!0),v=d[0],p=d[1],m=n(null),h=m[0],y=m[1],w=o(null),g=o(null),b=o(new Set),E=o(a);return E.current=a,r(function(){if("undefined"==typeof window)return p(!1),void y("WebRTC IP detection is not available during SSR");if("undefined"==typeof RTCPeerConnection)return p(!1),void y("RTCPeerConnection is not available");var n=new Set;b.current=n;var e=function(){g.current&&(clearTimeout(g.current),g.current=null),w.current&&(w.current.close(),w.current=null),p(!1)},r=function(e){n.has(e)||(n.add(e),l(function(n){return[].concat(n,[e])}),null==E.current||E.current(e))};try{var t=new RTCPeerConnection({iceServers:[{urls:u}]});w.current=t,t.onicecandidate=function(n){var e,t=n.candidate;t&&t.candidate&&((e=t.candidate.match(S))?[].concat(e):[]).forEach(r)},t.createDataChannel(""),t.createOffer().then(function(n){return t.setLocalDescription(n)}).catch(function(n){y(n instanceof Error?n.message:"Failed to create offer"),e()}),g.current=setTimeout(function(){return e()},c)}catch(n){y(n instanceof Error?n.message:"WebRTC setup failed"),e()}return function(){e()}},[u.join(","),c]),{ips:f,loading:v,error:h}}function D(t){var u=t.wasmUrl,i=t.exportName,c=void 0===i?"compute":i,a=t.workerUrl,s=t.importObject,f=n(void 0),l=f[0],d=f[1],v=n(!0),p=v[0],m=v[1],h=n(null),y=h[0],w=h[1],g=n(!1),b=g[0],E=g[1],k=o(null),P=o(null),x=o(null);return r(function(){if("undefined"==typeof window)return w("useWasmCompute is not available during SSR"),void m(!1);if("undefined"==typeof Worker)return w("Worker is not supported in this environment"),void m(!1);if("undefined"==typeof WebAssembly||"function"!=typeof WebAssembly.instantiate)return w("WebAssembly is not supported in this environment"),void m(!1);w(null),E(!1);var n=function(n){if(n)return new Worker(n);var e=new Blob(["\nself.onmessage = async (e) => {\n const d = e.data;\n if (d.type === 'init') {\n try {\n const res = await fetch(d.wasmUrl);\n const buf = await res.arrayBuffer();\n const mod = await WebAssembly.instantiate(buf, d.importObject || {});\n self.wasmInstance = mod.instance;\n self.exportName = d.exportName || 'compute';\n self.postMessage({ type: 'ready' });\n } catch (err) {\n self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n }\n return;\n }\n if (d.type === 'compute') {\n try {\n const fn = self.wasmInstance.exports[self.exportName];\n if (typeof fn !== 'function') {\n self.postMessage({ type: 'error', error: 'Export \"' + self.exportName + '\" is not a function' });\n return;\n }\n const result = fn(d.input);\n self.postMessage({ type: 'result', result: result });\n } catch (err) {\n self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n }\n }\n};\n"],{type:"application/javascript"}),r=URL.createObjectURL(e),t=new Worker(r);return URL.revokeObjectURL(r),t}(a);k.current=n;var e=function(n){var e,r=null!=(e=n.data)?e:{},t=r.type,o=r.result,u=r.error;return"ready"===t?(E(!0),void m(!1)):"error"===t?(w(null!=u?u:"Unknown error"),m(!1),void(x.current&&(x.current(new Error(u)),P.current=null,x.current=null))):void("result"===t&&(d(o),m(!1),P.current&&(P.current(o),P.current=null,x.current=null)))};return n.addEventListener("message",e),n.postMessage({type:"init",wasmUrl:u,exportName:c,importObject:null!=s?s:{}}),function(){n.removeEventListener("message",e),n.terminate(),k.current=null,x.current&&(x.current(new Error("Worker terminated")),P.current=null,x.current=null)}},[u,c,a,s]),{compute:e(function(n){return new Promise(function(e,r){k.current&&b?y?r(new Error(y)):(P.current=e,x.current=r,m(!0),k.current.postMessage({type:"compute",input:n})):r(new Error("WASM not ready"))})},[b,y]),result:l,loading:p,error:y,ready:b}}function L(e,u){void 0===u&&(u={});var i=u.maxHistory,c=void 0===i?100:i,a=u.throughputWindowMs,s=void 0===a?1e3:a,f=n([]),l=f[0],d=f[1],v=n(0),p=v[0],m=v[1],h=n(0),y=h[0],w=h[1],g=n([]),b=g[0],E=g[1],k=n(0),P=k[0],x=k[1],M=o([]),S=o(0),j=o(0);r(function(){if(e){var n=function(n){var e=function(n){if(null==n||"object"!=typeof n)return null;var e=n.type;return"task_start"!==e&&"task_end"!==e&&"task_fail"!==e&&"queue_size"!==e?null:{type:e,taskId:"string"==typeof n.taskId?n.taskId:void 0,duration:"number"==typeof n.duration?n.duration:void 0,error:"string"==typeof n.error?n.error:void 0,size:"number"==typeof n.size?n.size:void 0,timestamp:Date.now()}}(n.data);if(e)if(E(function(n){return[].concat(n,[e]).slice(-c)}),"task_start"===e.type&&e.taskId)d(function(n){return n.includes(e.taskId)?n:[].concat(n,[e.taskId])});else if("task_end"===e.type){e.taskId&&d(function(n){return n.filter(function(n){return n!==e.taskId})}),m(function(n){return n+1});var r=Date.now()-s;M.current=[].concat(M.current.filter(function(n){return n>=r}),[e.timestamp]),"number"==typeof e.duration&&(S.current+=e.duration,j.current+=1)}else"task_fail"===e.type?(e.taskId&&d(function(n){return n.filter(function(n){return n!==e.taskId})}),w(function(n){return n+1})):"queue_size"===e.type&&"number"==typeof e.size&&x(e.size)};return e.addEventListener("message",n),function(){return e.removeEventListener("message",n)}}},[e,c]);var I=t(function(){var n=j.current;return n>0?S.current/n:0},[b]),D=t(function(){var n=Date.now()-s;return M.current.filter(function(e){return e>=n}).length/(s/1e3)},[b,s]),L=t(function(){return{runningTasks:l,completedCount:p,failedCount:y,averageDurationMs:I,throughputPerSecond:D,currentQueueSize:P,totalProcessed:p+y,recentEventCount:b.length}},[l,p,y,I,D,P,b.length]);return{runningTasks:l,completedCount:p,failedCount:y,eventHistory:b,averageDurationMs:I,throughputPerSecond:D,currentQueueSize:P,progress:L}}export{g as useClipboard,f as useEventBus,M as useIndexedDB,a as useMutationObserver,y as useNetworkState,m as usePreferredTheme,b as useRageClick,E as useThreadedWorker,c as useTransition,D as useWasmCompute,I as useWebRTCIP,L as useWorkerNotifications,p as useWrappedChildren};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("react/hooks"),require("react")):"function"==typeof define&&define.amd?define(["exports","react/hooks","react"],n):n((e||self).preactMissingHooks={},e.hooks,e.react)}(this,function(e,n,r){var t=new Map;function o(e,n){(null==n||n>e.length)&&(n=e.length);for(var r=0,t=Array(n);r<n;r++)t[r]=e[r];return t}function u(e,n){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(r)return(r=r.call(e)).next.bind(r);if(Array.isArray(e)||(r=function(e,n){if(e){if("string"==typeof e)return o(e,n);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(e,n):void 0}}(e))||n&&e&&"number"==typeof e.length){r&&(e=r);var t=0;return function(){return t>=e.length?{done:!0}:{done:!1,value:e[t++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function i(){return i=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var r=arguments[n];for(var t in r)({}).hasOwnProperty.call(r,t)&&(e[t]=r[t])}return e},i.apply(null,arguments)}function a(){if("undefined"==typeof navigator)return{online:!0};var e={online:navigator.onLine},n=navigator.connection;return n&&(void 0!==n.effectiveType&&(e.effectiveType=n.effectiveType),void 0!==n.downlink&&(e.downlink=n.downlink),void 0!==n.rtt&&(e.rtt=n.rtt),void 0!==n.saveData&&(e.saveData=n.saveData),void 0!==n.type&&(e.connectionType=n.type)),e}function c(e,n){try{var r=e()}catch(e){return n(e)}return r&&r.then?r.then(void 0,n):r}var s=new Map;function f(e){return new Promise(function(n,r){e.onsuccess=function(){return n(e.result)},e.onerror=function(){var n;return r(null!=(n=e.error)?n:new DOMException("Unknown IndexedDB error"))}})}function l(e,n){return n?e.then(function(e){return null==n.onSuccess||n.onSuccess(e),e}).catch(function(e){throw null==n.onError||n.onError(e),e}):e}var d=/\b(?:25[0-5]|2[0-4]\d|1?\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|1?\d{1,2})){3}\b/g,v=["stun:stun.l.google.com:19302"];e.useClipboard=function(e){void 0===e&&(e={});var r=e.resetDelay,t=void 0===r?2e3:r,o=n.useState(!1),u=o[0],i=o[1],a=n.useState(null),s=a[0],f=a[1],l=n.useCallback(function(){i(!1),f(null)},[]);return{copy:n.useCallback(function(e){try{if(f(null),"undefined"==typeof navigator||!navigator.clipboard){var n=new Error("Clipboard API is not available");return f(n),Promise.resolve(!1)}return Promise.resolve(c(function(){return Promise.resolve(navigator.clipboard.writeText(e)).then(function(){return i(!0),t>0&&setTimeout(function(){return i(!1)},t),!0})},function(e){var n=e instanceof Error?e:new Error(String(e));return f(n),!1}))}catch(e){return Promise.reject(e)}},[t]),paste:n.useCallback(function(){try{if(f(null),"undefined"==typeof navigator||!navigator.clipboard){var e=new Error("Clipboard API is not available");return f(e),Promise.resolve("")}return Promise.resolve(c(function(){return Promise.resolve(navigator.clipboard.readText())},function(e){var n=e instanceof Error?e:new Error(String(e));return f(n),""}))}catch(e){return Promise.reject(e)}},[]),copied:u,error:s,reset:l}},e.useEventBus=function(){var e=n.useCallback(function(e){var n=arguments,r=t.get(e);r&&r.forEach(function(e){return e.apply(void 0,[].slice.call(n,1))})},[]);return{emit:e,on:n.useCallback(function(e,n){var r=t.get(e);return r||(r=new Set,t.set(e,r)),r.add(n),function(){r.delete(n),0===r.size&&t.delete(e)}},[])}},e.useIndexedDB=function(e){var r=n.useState(null),t=r[0],o=r[1],a=n.useState(null),c=a[0],d=a[1],v=n.useState(!1),p=v[0],m=v[1],h=n.useRef(e);return h.current=e,n.useEffect(function(){var e=!1;d(null),m(!1),o(null);var n=h.current;return function(e){var n=e.name+"_v"+e.version,r=s.get(n);return r||(r=function(e){return new Promise(function(n,r){var t=indexedDB.open(e.name,e.version);t.onerror=function(){var e;return r(null!=(e=t.error)?e:new DOMException("Failed to open database"))},t.onsuccess=function(){return n(t.result)},t.onupgradeneeded=function(n){for(var r=n.target.result,t=e.tables,o=0,i=Object.keys(t);o<i.length;o++){var a=i[o],c=t[a];if(!r.objectStoreNames.contains(a)){var s,f=r.createObjectStore(a,{keyPath:c.keyPath,autoIncrement:null!=(s=c.autoIncrement)&&s});if(c.indexes)for(var l,d=u(c.indexes);!(l=d()).done;){var v=l.value;f.createIndex(v,v,{unique:!1})}}}}})}(e),s.set(n,r),r)}({name:n.name,version:n.version,tables:n.tables}).then(function(n){if(e)n.close();else{var r=function(e){return{get db(){return e},hasTable:function(n){return e.objectStoreNames.contains(n)},table:function(n){return function(e,n){return function(e,n){function r(r){return e.transaction([n],r).objectStore(n)}return{insert:function(e,n){return l(f(r("readwrite").add(e)),n)},update:function(e,n,t){var o=r("readwrite");return l(f(o.get(e)).then(function(e){if(void 0===e)throw new DOMException("Key not found","NotFoundError");var r=i({},e,n);return f(o.put(r))}).then(function(){}),t)},delete:function(e,n){return l(f(r("readwrite").delete(e)).then(function(){}),n)},exists:function(e){return f(r("readonly").getKey(e)).then(function(e){return void 0!==e})},query:function(e,n){var t=r("readonly").openCursor(),o=[];return l(new Promise(function(n,r){t.onsuccess=function(){var r=t.result;r?(e(r.value)&&o.push(r.value),r.continue()):n(o)},t.onerror=function(){var e;return r(null!=(e=t.error)?e:new DOMException("Unknown error"))}}),n)},upsert:function(e,n){return l(f(r("readwrite").put(e)),n)},bulkInsert:function(e,n){var t=r("readwrite"),o=[];if(0===e.length)return l(Promise.resolve(o),n);var u=0;return l(new Promise(function(n,r){e.forEach(function(i,a){var c=t.add(i);c.onsuccess=function(){o[a]=c.result,++u===e.length&&n(o)},c.onerror=function(){var e;return r(null!=(e=c.error)?e:new DOMException("Unknown error"))}})}),n)},clear:function(e){return l(f(r("readwrite").clear()).then(function(){}),e)},count:function(e){return l(f(r("readonly").count()),null!=e?e:{})}}}(e,n)}(e,n)},transaction:function(n,r,t,o){var u=e.transaction(n,r),a={table:function(e){return function(e,n){return function(e,n){function r(){return e.objectStore(n)}return{insert:function(e,n){return l(f(r().add(e)),n)},update:function(e,n,t){var o=r();return l(f(o.get(e)).then(function(e){if(void 0===e)throw new DOMException("Key not found","NotFoundError");var r=i({},e,n);return f(o.put(r))}).then(function(){}),t)},delete:function(e,n){return l(f(r().delete(e)).then(function(){}),n)},exists:function(e){return f(r().getKey(e)).then(function(e){return void 0!==e})},query:function(e,n){var t=r().openCursor(),o=[];return l(new Promise(function(n,r){t.onsuccess=function(){var r=t.result;r?(e(r.value)&&o.push(r.value),r.continue()):n(o)},t.onerror=function(){var e;return r(null!=(e=t.error)?e:new DOMException("Unknown error"))}}),n)},upsert:function(e,n){return l(f(r().put(e)),n)},bulkInsert:function(e,n){var t=r(),o=[];if(0===e.length)return l(Promise.resolve(o),n);var u=0;return l(new Promise(function(n,r){e.forEach(function(i,a){var c=t.add(i);c.onsuccess=function(){o[a]=c.result,++u===e.length&&n(o)},c.onerror=function(){var e;return r(null!=(e=c.error)?e:new DOMException("Unknown error"))}})}),n)},clear:function(e){return l(f(r().clear()).then(function(){}),e)},count:function(e){return l(f(r().count()),null!=e?e:{})}}}(e,n)}(u,e)}},c=new Promise(function(e,n){u.oncomplete=function(){return e()},u.onerror=function(){var e;return n(null!=(e=u.error)?e:new DOMException("Transaction failed"))}}),s=t(a);return function(e,n){return n?e.then(function(){return null==n.onSuccess?void 0:n.onSuccess()}).catch(function(e){throw null==n.onError||n.onError(e),e}):e}(Promise.resolve(s).then(function(){return c}),o)}}}(n);o(r),m(!0)}}).catch(function(n){e||d(n)}),function(){e=!0}},[e.name,e.version]),{db:t,isReady:p,error:c}},e.useMutationObserver=function(e,r,t){n.useEffect(function(){var n=e.current;if(n){var o=new MutationObserver(r);return o.observe(n,t),function(){return o.disconnect()}}},[e,r,t])},e.useNetworkState=function(){var e=n.useState(a),r=e[0],t=e[1];return n.useEffect(function(){if("undefined"!=typeof window){var e=function(){return t(a())};window.addEventListener("online",e),window.addEventListener("offline",e);var n=navigator.connection;return null!=n&&n.addEventListener&&n.addEventListener("change",e),function(){window.removeEventListener("online",e),window.removeEventListener("offline",e),null!=n&&n.removeEventListener&&n.removeEventListener("change",e)}}},[]),r},e.usePreferredTheme=function(){var e=n.useState(function(){if("undefined"==typeof window)return"no-preference";var e=window.matchMedia("(prefers-color-scheme: dark)"),n=window.matchMedia("(prefers-color-scheme: light)");return e.matches?"dark":n.matches?"light":"no-preference"}),r=e[0],t=e[1];return n.useEffect(function(){if("undefined"!=typeof window){var e=window.matchMedia("(prefers-color-scheme: dark)"),n=function(e){t(e.matches?"dark":"light")},r=function(){var e=window.matchMedia("(prefers-color-scheme: dark)"),n=window.matchMedia("(prefers-color-scheme: light)");t(e.matches?"dark":n.matches?"light":"no-preference")};e.addEventListener("change",n);var o=window.matchMedia("(prefers-color-scheme: light)");return o.addEventListener("change",r),function(){e.removeEventListener("change",n),o.removeEventListener("change",r)}}},[]),r},e.useRageClick=function(e,r){var t=r.onRageClick,o=r.threshold,u=void 0===o?5:o,i=r.timeWindow,a=void 0===i?1e3:i,c=r.distanceThreshold,s=void 0===c?30:c,f=n.useRef(t);f.current=t;var l=n.useRef([]);n.useEffect(function(){var n=e.current;if(n){var r=function(e){var n=Date.now(),r={time:n,x:e.clientX,y:e.clientY},t=n-a,o=l.current.filter(function(e){return e.time>=t});if(o.push(r),Infinity!==s){var i=o.filter(function(e){return n=e,t=r,Math.hypot(t.x-n.x,t.y-n.y)<=s;var n,t});if(i.length>=u)return f.current({count:i.length,event:e}),void(l.current=[])}else if(o.length>=u)return f.current({count:o.length,event:e}),void(l.current=[]);l.current=o};return n.addEventListener("click",r),function(){return n.removeEventListener("click",r)}}},[e,u,a,s])},e.useThreadedWorker=function(e,r){var t=r.concurrency,o="sequential"===r.mode?1:Math.max(1,void 0===t?4:t),u=n.useState(!1),i=u[0],a=u[1],c=n.useState(void 0),s=c[0],f=c[1],l=n.useState(void 0),d=l[0],v=l[1],p=n.useState(0),m=p[0],h=p[1],y=n.useRef([]),w=n.useRef(0),g=n.useRef(0),b=n.useRef(!1),k=n.useRef(e);k.current=e;var E=n.useCallback(function(){h(y.current.length+g.current)},[]),S=n.useCallback(function(){if(!(b.current||g.current>=o)){if(0===y.current.length)return 0===g.current&&a(!1),void E();y.current.sort(function(e,n){return e.priority!==n.priority?e.priority-n.priority:e.sequence-n.sequence});var e=y.current.shift();g.current+=1,a(!0),E(),(0,k.current)(e.data).then(function(n){f(n),v(void 0),e.resolve(n)}).catch(function(n){v(n),e.reject(n)}).finally(function(){g.current-=1,E(),S()}),y.current.length>0&&g.current<o&&S()}},[o,E]),M=n.useCallback(function(e,n){var r;if(b.current)return Promise.reject(new Error("Worker is terminated"));var t=null!=(r=null==n?void 0:n.priority)?r:1,o=++w.current,u=new Promise(function(n,r){y.current.push({data:e,priority:t,sequence:o,resolve:n,reject:r})});return E(),a(!0),queueMicrotask(S),u},[S,E]),C=n.useCallback(function(){var e=y.current;y.current=[],e.forEach(function(e){return e.reject(new Error("Task cleared from queue"))}),E(),0===g.current&&a(!1)},[E]),x=n.useCallback(function(){b.current=!0,C()},[C]);return n.useEffect(function(){return function(){b.current=!0}},[]),{run:M,loading:i,result:s,error:d,queueSize:m,clearQueue:C,terminate:x}},e.useTransition=function(){var e=n.useState(!1),r=e[0],t=e[1];return[n.useCallback(function(e){t(!0),Promise.resolve().then(function(){e(),t(!1)})},[]),r]},e.useWasmCompute=function(e){var r=e.wasmUrl,t=e.exportName,o=void 0===t?"compute":t,u=e.workerUrl,i=e.importObject,a=n.useState(void 0),c=a[0],s=a[1],f=n.useState(!0),l=f[0],d=f[1],v=n.useState(null),p=v[0],m=v[1],h=n.useState(!1),y=h[0],w=h[1],g=n.useRef(null),b=n.useRef(null),k=n.useRef(null);return n.useEffect(function(){if("undefined"==typeof window)return m("useWasmCompute is not available during SSR"),void d(!1);if("undefined"==typeof Worker)return m("Worker is not supported in this environment"),void d(!1);if("undefined"==typeof WebAssembly||"function"!=typeof WebAssembly.instantiate)return m("WebAssembly is not supported in this environment"),void d(!1);m(null),w(!1);var e=function(e){if(e)return new Worker(e);var n=new Blob(["\nself.onmessage = async (e) => {\n const d = e.data;\n if (d.type === 'init') {\n try {\n const res = await fetch(d.wasmUrl);\n const buf = await res.arrayBuffer();\n const mod = await WebAssembly.instantiate(buf, d.importObject || {});\n self.wasmInstance = mod.instance;\n self.exportName = d.exportName || 'compute';\n self.postMessage({ type: 'ready' });\n } catch (err) {\n self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n }\n return;\n }\n if (d.type === 'compute') {\n try {\n const fn = self.wasmInstance.exports[self.exportName];\n if (typeof fn !== 'function') {\n self.postMessage({ type: 'error', error: 'Export \"' + self.exportName + '\" is not a function' });\n return;\n }\n const result = fn(d.input);\n self.postMessage({ type: 'result', result: result });\n } catch (err) {\n self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n }\n }\n};\n"],{type:"application/javascript"}),r=URL.createObjectURL(n),t=new Worker(r);return URL.revokeObjectURL(r),t}(u);g.current=e;var n=function(e){var n,r=null!=(n=e.data)?n:{},t=r.type,o=r.result,u=r.error;return"ready"===t?(w(!0),void d(!1)):"error"===t?(m(null!=u?u:"Unknown error"),d(!1),void(k.current&&(k.current(new Error(u)),b.current=null,k.current=null))):void("result"===t&&(s(o),d(!1),b.current&&(b.current(o),b.current=null,k.current=null)))};return e.addEventListener("message",n),e.postMessage({type:"init",wasmUrl:r,exportName:o,importObject:null!=i?i:{}}),function(){e.removeEventListener("message",n),e.terminate(),g.current=null,k.current&&(k.current(new Error("Worker terminated")),b.current=null,k.current=null)}},[r,o,u,i]),{compute:n.useCallback(function(e){return new Promise(function(n,r){g.current&&y?p?r(new Error(p)):(b.current=n,k.current=r,d(!0),g.current.postMessage({type:"compute",input:e})):r(new Error("WASM not ready"))})},[y,p]),result:c,loading:l,error:p,ready:y}},e.useWebRTCIP=function(e){void 0===e&&(e={});var r=e.stunServers,t=void 0===r?v:r,o=e.timeout,u=void 0===o?3e3:o,i=e.onDetect,a=n.useState([]),c=a[0],s=a[1],f=n.useState(!0),l=f[0],p=f[1],m=n.useState(null),h=m[0],y=m[1],w=n.useRef(null),g=n.useRef(null),b=n.useRef(new Set),k=n.useRef(i);return k.current=i,n.useEffect(function(){if("undefined"==typeof window)return p(!1),void y("WebRTC IP detection is not available during SSR");if("undefined"==typeof RTCPeerConnection)return p(!1),void y("RTCPeerConnection is not available");var e=new Set;b.current=e;var n=function(){g.current&&(clearTimeout(g.current),g.current=null),w.current&&(w.current.close(),w.current=null),p(!1)},r=function(n){e.has(n)||(e.add(n),s(function(e){return[].concat(e,[n])}),null==k.current||k.current(n))};try{var o=new RTCPeerConnection({iceServers:[{urls:t}]});w.current=o,o.onicecandidate=function(e){var n,t=e.candidate;t&&t.candidate&&((n=t.candidate.match(d))?[].concat(n):[]).forEach(r)},o.createDataChannel(""),o.createOffer().then(function(e){return o.setLocalDescription(e)}).catch(function(e){y(e instanceof Error?e.message:"Failed to create offer"),n()}),g.current=setTimeout(function(){return n()},u)}catch(e){y(e instanceof Error?e.message:"WebRTC setup failed"),n()}return function(){n()}},[t.join(","),u]),{ips:c,loading:l,error:h}},e.useWorkerNotifications=function(e,r){void 0===r&&(r={});var t=r.maxHistory,o=void 0===t?100:t,u=r.throughputWindowMs,i=void 0===u?1e3:u,a=n.useState([]),c=a[0],s=a[1],f=n.useState(0),l=f[0],d=f[1],v=n.useState(0),p=v[0],m=v[1],h=n.useState([]),y=h[0],w=h[1],g=n.useState(0),b=g[0],k=g[1],E=n.useRef([]),S=n.useRef(0),M=n.useRef(0);n.useEffect(function(){if(e){var n=function(e){var n=function(e){if(null==e||"object"!=typeof e)return null;var n=e.type;return"task_start"!==n&&"task_end"!==n&&"task_fail"!==n&&"queue_size"!==n?null:{type:n,taskId:"string"==typeof e.taskId?e.taskId:void 0,duration:"number"==typeof e.duration?e.duration:void 0,error:"string"==typeof e.error?e.error:void 0,size:"number"==typeof e.size?e.size:void 0,timestamp:Date.now()}}(e.data);if(n)if(w(function(e){return[].concat(e,[n]).slice(-o)}),"task_start"===n.type&&n.taskId)s(function(e){return e.includes(n.taskId)?e:[].concat(e,[n.taskId])});else if("task_end"===n.type){n.taskId&&s(function(e){return e.filter(function(e){return e!==n.taskId})}),d(function(e){return e+1});var r=Date.now()-i;E.current=[].concat(E.current.filter(function(e){return e>=r}),[n.timestamp]),"number"==typeof n.duration&&(S.current+=n.duration,M.current+=1)}else"task_fail"===n.type?(n.taskId&&s(function(e){return e.filter(function(e){return e!==n.taskId})}),m(function(e){return e+1})):"queue_size"===n.type&&"number"==typeof n.size&&k(n.size)};return e.addEventListener("message",n),function(){return e.removeEventListener("message",n)}}},[e,o]);var C=n.useMemo(function(){var e=M.current;return e>0?S.current/e:0},[y]),x=n.useMemo(function(){var e=Date.now()-i;return E.current.filter(function(n){return n>=e}).length/(i/1e3)},[y,i]),P=n.useMemo(function(){return{runningTasks:c,completedCount:l,failedCount:p,averageDurationMs:C,throughputPerSecond:x,currentQueueSize:b,totalProcessed:l+p,recentEventCount:y.length}},[c,l,p,C,x,b,y.length]);return{runningTasks:c,completedCount:l,failedCount:p,eventHistory:y,averageDurationMs:C,throughputPerSecond:x,currentQueueSize:b,progress:P}},e.useWrappedChildren=function(e,t,o){return void 0===o&&(o="preserve"),n.useMemo(function(){if(!e)return e;var n=function(e){if(!r.isValidElement(e))return e;var n,u=e.props||{};n="override"===o?i({},u,t):i({},t,u);var a=null==u?void 0:u.style,c=null==t?void 0:t.style;return a&&c&&"object"==typeof a&&"object"==typeof c&&(n.style="override"===o?i({},a,c):i({},c,a)),r.cloneElement(e,n)};return Array.isArray(e)?e.map(n):n(e)},[e,t,o])}});
|
package/dist/useEventBus.d.ts
CHANGED
package/dist/useIndexedDB.d.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Uses a singleton connection per (name, version).
|
|
4
4
|
* @module useIndexedDB
|
|
5
5
|
*/
|
|
6
|
-
import type { IndexedDBConfig } from
|
|
7
|
-
import type { IDBController } from
|
|
8
|
-
export type { IndexedDBConfig, IDBController } from
|
|
6
|
+
import type { IndexedDBConfig } from "./indexedDB/types";
|
|
7
|
+
import type { IDBController } from "./indexedDB/dbController";
|
|
8
|
+
export type { IndexedDBConfig, IDBController } from "./indexedDB";
|
|
9
9
|
export interface UseIndexedDBReturn {
|
|
10
10
|
/** Database controller (table, transaction). Null until the database is open. */
|
|
11
11
|
db: IDBController | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Effective connection type from Network Information API */
|
|
2
|
-
export type EffectiveConnectionType =
|
|
2
|
+
export type EffectiveConnectionType = "slow-2g" | "2g" | "3g" | "4g";
|
|
3
3
|
/** Network connection type (e.g., wifi, cellular) */
|
|
4
|
-
export type ConnectionType =
|
|
4
|
+
export type ConnectionType = "bluetooth" | "cellular" | "ethernet" | "mixed" | "none" | "other" | "unknown" | "wifi";
|
|
5
5
|
export interface NetworkState {
|
|
6
6
|
/** Whether the browser is online */
|
|
7
7
|
online: boolean;
|
|
@@ -33,7 +33,7 @@ export interface NetworkState {
|
|
|
33
33
|
* {effectiveType && ` (${effectiveType})`}
|
|
34
34
|
* {saveData && ' - Reduced data mode'}
|
|
35
35
|
* </div>
|
|
36
|
-
|
|
36
|
+
* );
|
|
37
37
|
* }
|
|
38
38
|
* ```
|
|
39
39
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type PreferredTheme =
|
|
1
|
+
export type PreferredTheme = "light" | "dark" | "no-preference";
|
|
2
2
|
/**
|
|
3
3
|
* A Preact hook that returns the user's preferred color scheme based on the
|
|
4
4
|
* `prefers-color-scheme` media query. Updates reactively when the user changes
|
package/dist/useRageClick.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ThreadedWorkerMode =
|
|
1
|
+
export type ThreadedWorkerMode = "sequential" | "parallel";
|
|
2
2
|
export interface UseThreadedWorkerOptions {
|
|
3
3
|
/** Sequential: single worker, priority-ordered. Parallel: worker pool. */
|
|
4
4
|
mode: ThreadedWorkerMode;
|
package/dist/useTransition.d.ts
CHANGED
|
@@ -2,4 +2,7 @@
|
|
|
2
2
|
* Mimics React's useTransition hook in Preact.
|
|
3
3
|
* @returns [startTransition, isPending]
|
|
4
4
|
*/
|
|
5
|
-
export declare function useTransition(): [
|
|
5
|
+
export declare function useTransition(): [
|
|
6
|
+
startTransition: (callback: () => void) => void,
|
|
7
|
+
isPending: boolean
|
|
8
|
+
];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module useWorkerNotifications
|
|
4
4
|
*/
|
|
5
5
|
/** Supported worker event types for tracking. Worker should postMessage with these shapes. */
|
|
6
|
-
export type WorkerEventType =
|
|
6
|
+
export type WorkerEventType = "task_start" | "task_end" | "task_fail" | "queue_size";
|
|
7
7
|
export interface WorkerNotificationEvent {
|
|
8
8
|
type: WorkerEventType;
|
|
9
9
|
taskId?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ComponentChildren } from
|
|
2
|
-
export type InjectableProps = Record<string,
|
|
1
|
+
import { ComponentChildren } from "preact";
|
|
2
|
+
export type InjectableProps = Record<string, unknown>;
|
|
3
3
|
/**
|
|
4
4
|
* A Preact hook to wrap children components and inject additional props into them.
|
|
5
5
|
* @param children - The children to wrap and enhance with props.
|
|
@@ -7,4 +7,4 @@ export type InjectableProps = Record<string, any>;
|
|
|
7
7
|
* @param mergeStrategy - How to handle prop conflicts ('override' | 'preserve'). Defaults to 'preserve'.
|
|
8
8
|
* @returns Enhanced children with injected props.
|
|
9
9
|
*/
|
|
10
|
-
export declare function useWrappedChildren(children: ComponentChildren, injectProps: InjectableProps, mergeStrategy?:
|
|
10
|
+
export declare function useWrappedChildren(children: ComponentChildren, injectProps: InjectableProps, mergeStrategy?: "override" | "preserve"): ComponentChildren;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import eslint from "@eslint/js";
|
|
2
|
+
import { defineConfig } from "eslint/config";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
import prettier from "eslint-config-prettier";
|
|
5
|
+
|
|
6
|
+
export default defineConfig(
|
|
7
|
+
eslint.configs.recommended,
|
|
8
|
+
tseslint.configs.recommended,
|
|
9
|
+
prettier
|
|
10
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "preact-missing-hooks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A lightweight, extendable collection of missing React-like hooks for Preact — plus fresh, powerful new ones designed specifically for modern Preact apps.",
|
|
5
5
|
"author": "Prakhar Dubey",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"import":
|
|
15
|
-
|
|
14
|
+
"import": {
|
|
15
|
+
"react": "./dist/react.module.js",
|
|
16
|
+
"default": "./dist/index.module.js"
|
|
17
|
+
},
|
|
18
|
+
"require": "./dist/entry.cjs"
|
|
16
19
|
},
|
|
17
20
|
"./useTransition": {
|
|
18
21
|
"types": "./dist/useTransition.d.ts",
|
|
@@ -78,16 +81,47 @@
|
|
|
78
81
|
"types": "./dist/useWorkerNotifications.d.ts",
|
|
79
82
|
"import": "./dist/useWorkerNotifications.module.js",
|
|
80
83
|
"require": "./dist/useWorkerNotifications.js"
|
|
84
|
+
},
|
|
85
|
+
"./react": {
|
|
86
|
+
"types": "./dist/index.d.ts",
|
|
87
|
+
"import": "./dist/react.module.js",
|
|
88
|
+
"require": "./dist/react.js"
|
|
81
89
|
}
|
|
82
90
|
},
|
|
83
91
|
"scripts": {
|
|
84
|
-
"build": "microbundle",
|
|
92
|
+
"build": "microbundle && npm run build:react && node scripts/generate-entry.cjs",
|
|
93
|
+
"build:react": "microbundle -i src/index.ts -o dist/react.js --alias preact=react,preact/hooks=react --no-sourcemap",
|
|
85
94
|
"dev": "microbundle watch",
|
|
86
95
|
"prepublishOnly": "npm run build",
|
|
87
96
|
"test": "vitest run",
|
|
97
|
+
"test:preact": "vitest run --project preact",
|
|
98
|
+
"test:react": "vitest run --project react",
|
|
88
99
|
"type-check": "tsc --noEmit",
|
|
89
|
-
"demo": "npx serve -l 5000"
|
|
100
|
+
"demo": "npx serve -l 5000",
|
|
101
|
+
"lint": "eslint src",
|
|
102
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
|
|
103
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
|
|
104
|
+
"prepare": "husky",
|
|
105
|
+
"size": "npm run build && size-limit"
|
|
90
106
|
},
|
|
107
|
+
"size-limit": [
|
|
108
|
+
{
|
|
109
|
+
"path": "dist/index.module.js",
|
|
110
|
+
"limit": "20 KB"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"path": "dist/index.js",
|
|
114
|
+
"limit": "20 KB"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"path": "dist/react.module.js",
|
|
118
|
+
"limit": "20 KB"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"path": "dist/react.js",
|
|
122
|
+
"limit": "20 KB"
|
|
123
|
+
}
|
|
124
|
+
],
|
|
91
125
|
"keywords": [
|
|
92
126
|
"preact",
|
|
93
127
|
"hooks",
|
|
@@ -114,16 +148,36 @@
|
|
|
114
148
|
"preact": ">=10.0.0"
|
|
115
149
|
},
|
|
116
150
|
"devDependencies": {
|
|
151
|
+
"@eslint/js": "^9.15.0",
|
|
152
|
+
"@size-limit/file": "^11.2.0",
|
|
117
153
|
"@testing-library/jest-dom": "^6.6.3",
|
|
118
154
|
"@testing-library/preact": "^3.2.4",
|
|
155
|
+
"@testing-library/react": "^16.0.1",
|
|
119
156
|
"@types/jest": "^29.5.14",
|
|
157
|
+
"eslint": "^9.15.0",
|
|
158
|
+
"eslint-config-prettier": "^9.1.0",
|
|
120
159
|
"fake-indexeddb": "^6.0.2",
|
|
160
|
+
"husky": "^9.1.7",
|
|
121
161
|
"jsdom": "^26.1.0",
|
|
122
162
|
"microbundle": "^0.15.1",
|
|
163
|
+
"prettier": "^3.3.3",
|
|
164
|
+
"react": "^18.3.1",
|
|
165
|
+
"react-dom": "^18.3.1",
|
|
166
|
+
"size-limit": "^11.2.0",
|
|
123
167
|
"typescript": "^5.8.3",
|
|
168
|
+
"typescript-eslint": "^8.15.0",
|
|
124
169
|
"vitest": "^3.1.4"
|
|
125
170
|
},
|
|
126
171
|
"peerDependencies": {
|
|
127
|
-
"preact": ">=10.0.0"
|
|
172
|
+
"preact": ">=10.0.0",
|
|
173
|
+
"react": ">=17.0.0"
|
|
174
|
+
},
|
|
175
|
+
"peerDependenciesMeta": {
|
|
176
|
+
"preact": {
|
|
177
|
+
"optional": true
|
|
178
|
+
},
|
|
179
|
+
"react": {
|
|
180
|
+
"optional": true
|
|
181
|
+
}
|
|
128
182
|
}
|
|
129
183
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates dist/entry.cjs which auto-detects Preact vs React at runtime (CJS only).
|
|
3
|
+
* Run after build so dist/index.js and dist/react.js exist.
|
|
4
|
+
*/
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
const content = `"use strict";
|
|
9
|
+
/**
|
|
10
|
+
* Auto-detect Preact vs React and re-export the matching build.
|
|
11
|
+
* Used for require('preact-missing-hooks') in Node / CJS bundlers.
|
|
12
|
+
*/
|
|
13
|
+
function detect() {
|
|
14
|
+
try {
|
|
15
|
+
require.resolve("preact");
|
|
16
|
+
return require("./index.js");
|
|
17
|
+
} catch (_) {
|
|
18
|
+
try {
|
|
19
|
+
require.resolve("react");
|
|
20
|
+
return require("./react.js");
|
|
21
|
+
} catch (_) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
"preact-missing-hooks: Install either \\"preact\\" or \\"react\\" in your project."
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
module.exports = detect();
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const outPath = path.join(__dirname, "..", "dist", "entry.cjs");
|
|
32
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
33
|
+
fs.writeFileSync(outPath, content, "utf8");
|
|
34
|
+
console.log("Generated dist/entry.cjs");
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export * from
|
|
10
|
-
export * from
|
|
11
|
-
export * from
|
|
12
|
-
export * from
|
|
13
|
-
export * from
|
|
1
|
+
export * from "./useTransition";
|
|
2
|
+
export * from "./useMutationObserver";
|
|
3
|
+
export * from "./useEventBus";
|
|
4
|
+
export * from "./useWrappedChildren";
|
|
5
|
+
export * from "./usePreferredTheme";
|
|
6
|
+
export * from "./useNetworkState";
|
|
7
|
+
export * from "./useClipboard";
|
|
8
|
+
export * from "./useRageClick";
|
|
9
|
+
export * from "./useThreadedWorker";
|
|
10
|
+
export * from "./useIndexedDB";
|
|
11
|
+
export * from "./useWebRTCIP";
|
|
12
|
+
export * from "./useWasmCompute";
|
|
13
|
+
export * from "./useWorkerNotifications";
|
|
@@ -1,92 +1,101 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Database controller: table(name), transaction(storeNames, mode, callback, options).
|
|
3
|
-
* @module indexedDB/dbController
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { IndexedDBConfig, TransactionOptions } from
|
|
7
|
-
import type { ITableController } from
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
* @param
|
|
33
|
-
* @
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Database controller: table(name), transaction(storeNames, mode, callback, options).
|
|
3
|
+
* @module indexedDB/dbController
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { IndexedDBConfig, TransactionOptions } from "./types";
|
|
7
|
+
import type { ITableController } from "./tableController";
|
|
8
|
+
import {
|
|
9
|
+
createTableController,
|
|
10
|
+
createTransactionTableController,
|
|
11
|
+
} from "./tableController";
|
|
12
|
+
|
|
13
|
+
/** Transaction context passed to the callback: provides table(name) bound to this transaction. */
|
|
14
|
+
export interface TransactionContext {
|
|
15
|
+
/** Returns a table controller bound to this transaction. Use for all ops inside the callback. */
|
|
16
|
+
table: (name: string) => ITableController;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Database controller built from an open IDBDatabase.
|
|
21
|
+
* Exposes table(name) and transaction(...).
|
|
22
|
+
*/
|
|
23
|
+
export interface IDBController {
|
|
24
|
+
/** Underlying IDBDatabase (read-only). */
|
|
25
|
+
readonly db: IDBDatabase;
|
|
26
|
+
/** Returns true if an object store with the given name exists. */
|
|
27
|
+
hasTable: (name: string) => boolean;
|
|
28
|
+
/** Returns a table controller for the given store (each op opens its own transaction). */
|
|
29
|
+
table: (name: string) => ITableController;
|
|
30
|
+
/**
|
|
31
|
+
* Runs a callback inside a single transaction. All operations in the callback use the same transaction.
|
|
32
|
+
* @param storeNames - Object store names to include in the transaction.
|
|
33
|
+
* @param mode - 'readonly' | 'readwrite'.
|
|
34
|
+
* @param callback - Async or sync function receiving { table(name) }. Return value is ignored; await all ops inside.
|
|
35
|
+
* @param options - Optional onSuccess/onError callbacks.
|
|
36
|
+
* @returns Promise that resolves when the transaction completes (after all requests and the callback).
|
|
37
|
+
*/
|
|
38
|
+
transaction: <T = void>(
|
|
39
|
+
storeNames: string[],
|
|
40
|
+
mode: IDBTransactionMode,
|
|
41
|
+
callback: (tx: TransactionContext) => T | Promise<T>,
|
|
42
|
+
options?: TransactionOptions
|
|
43
|
+
) => Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function withTransactionCallbacks(
|
|
47
|
+
promise: Promise<void>,
|
|
48
|
+
options?: TransactionOptions
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
if (!options) return promise;
|
|
51
|
+
return promise
|
|
52
|
+
.then(() => options.onSuccess?.())
|
|
53
|
+
.catch((err: DOMException) => {
|
|
54
|
+
options.onError?.(err);
|
|
55
|
+
throw err;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Creates a database controller from an open IDBDatabase instance.
|
|
61
|
+
*/
|
|
62
|
+
export function createDBController(
|
|
63
|
+
db: IDBDatabase,
|
|
64
|
+
_config: IndexedDBConfig
|
|
65
|
+
): IDBController {
|
|
66
|
+
void _config; // Reserved for future config options
|
|
67
|
+
return {
|
|
68
|
+
get db(): IDBDatabase {
|
|
69
|
+
return db;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
hasTable(name: string): boolean {
|
|
73
|
+
return db.objectStoreNames.contains(name);
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
table(name: string): ITableController {
|
|
77
|
+
return createTableController(db, name);
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
transaction<T = void>(
|
|
81
|
+
storeNames: string[],
|
|
82
|
+
mode: IDBTransactionMode,
|
|
83
|
+
callback: (tx: TransactionContext) => T | Promise<T>,
|
|
84
|
+
options?: TransactionOptions
|
|
85
|
+
): Promise<void> {
|
|
86
|
+
const tx = db.transaction(storeNames, mode);
|
|
87
|
+
const txContext: TransactionContext = {
|
|
88
|
+
table: (tableName: string) =>
|
|
89
|
+
createTransactionTableController(tx, tableName),
|
|
90
|
+
};
|
|
91
|
+
const txPromise = new Promise<void>((resolve, reject) => {
|
|
92
|
+
tx.oncomplete = () => resolve();
|
|
93
|
+
tx.onerror = () =>
|
|
94
|
+
reject(tx.error ?? new DOMException("Transaction failed"));
|
|
95
|
+
});
|
|
96
|
+
const callbackResult = callback(txContext);
|
|
97
|
+
const promise = Promise.resolve(callbackResult).then(() => txPromise);
|
|
98
|
+
return withTransactionCallbacks(promise, options);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|