preact-missing-hooks 3.0.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.
Files changed (79) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.husky/pre-push +1 -0
  3. package/.prettierignore +3 -0
  4. package/.prettierrc +6 -0
  5. package/Readme.md +179 -131
  6. package/dist/entry.cjs +21 -0
  7. package/dist/entry.js +2 -0
  8. package/dist/entry.js.map +1 -0
  9. package/dist/entry.modern.mjs +2 -0
  10. package/dist/entry.modern.mjs.map +1 -0
  11. package/dist/entry.module.js +2 -0
  12. package/dist/entry.module.js.map +1 -0
  13. package/dist/entry.umd.js +2 -0
  14. package/dist/entry.umd.js.map +1 -0
  15. package/dist/index.d.ts +13 -12
  16. package/dist/index.js +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.modern.mjs +2 -0
  19. package/dist/index.modern.mjs.map +1 -0
  20. package/dist/index.module.js +1 -1
  21. package/dist/index.module.js.map +1 -1
  22. package/dist/index.umd.js +1 -1
  23. package/dist/index.umd.js.map +1 -1
  24. package/dist/indexedDB/dbController.d.ts +2 -2
  25. package/dist/indexedDB/index.d.ts +6 -6
  26. package/dist/indexedDB/openDB.d.ts +1 -1
  27. package/dist/indexedDB/tableController.d.ts +1 -1
  28. package/dist/indexedDB/types.d.ts +1 -2
  29. package/dist/react.js +1 -0
  30. package/dist/react.modern.mjs +1 -0
  31. package/dist/react.module.js +1 -0
  32. package/dist/react.umd.js +1 -0
  33. package/dist/useEventBus.d.ts +1 -1
  34. package/dist/useIndexedDB.d.ts +3 -3
  35. package/dist/useMutationObserver.d.ts +1 -1
  36. package/dist/useNetworkState.d.ts +3 -3
  37. package/dist/usePreferredTheme.d.ts +1 -1
  38. package/dist/useRageClick.d.ts +1 -1
  39. package/dist/useThreadedWorker.d.ts +1 -1
  40. package/dist/useTransition.d.ts +4 -1
  41. package/dist/useWorkerNotifications.d.ts +57 -0
  42. package/dist/useWrappedChildren.d.ts +3 -3
  43. package/{demo → docs}/index.html +56 -0
  44. package/{demo → docs}/main.js +437 -312
  45. package/eslint.config.mjs +10 -0
  46. package/package.json +65 -6
  47. package/scripts/generate-entry.cjs +34 -0
  48. package/src/index.ts +13 -12
  49. package/src/indexedDB/dbController.ts +101 -92
  50. package/src/indexedDB/index.ts +16 -11
  51. package/src/indexedDB/openDB.ts +49 -49
  52. package/src/indexedDB/requestToPromise.ts +17 -16
  53. package/src/indexedDB/tableController.ts +331 -257
  54. package/src/indexedDB/types.ts +35 -35
  55. package/src/useClipboard.ts +99 -97
  56. package/src/useEventBus.ts +39 -36
  57. package/src/useIndexedDB.ts +111 -111
  58. package/src/useMutationObserver.ts +26 -26
  59. package/src/useNetworkState.ts +124 -122
  60. package/src/usePreferredTheme.ts +68 -68
  61. package/src/useRageClick.ts +103 -103
  62. package/src/useThreadedWorker.ts +165 -165
  63. package/src/useTransition.ts +22 -19
  64. package/src/useWasmCompute.ts +209 -204
  65. package/src/useWebRTCIP.ts +181 -176
  66. package/src/useWorkerNotifications.ts +203 -0
  67. package/src/useWrappedChildren.ts +72 -58
  68. package/tests/react-adapter.tsx +12 -0
  69. package/tests/setup-react.ts +4 -0
  70. package/tests/useClipboard.test.tsx +4 -2
  71. package/tests/useThreadedWorker.test.tsx +3 -1
  72. package/tests/useWasmCompute.test.tsx +1 -1
  73. package/tests/useWebRTCIP.test.tsx +3 -1
  74. package/tests/useWorkerNotifications.test.tsx +170 -0
  75. package/vite.config.ts +11 -4
  76. package/vitest.config.preact.ts +20 -0
  77. package/vitest.config.react.ts +36 -0
  78. package/vitest.workspace.ts +6 -0
  79. /package/{demo → docs}/add.wasm +0 -0
@@ -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])}});
@@ -1,4 +1,4 @@
1
- type EventMap = Record<string, (...args: any[]) => void>;
1
+ type EventMap = Record<string, (...args: unknown[]) => void>;
2
2
  /**
3
3
  * A Preact hook to publish and subscribe to custom events across components.
4
4
  * @returns An object with `emit` and `on` methods.
@@ -3,9 +3,9 @@
3
3
  * Uses a singleton connection per (name, version).
4
4
  * @module useIndexedDB
5
5
  */
6
- import type { IndexedDBConfig } from './indexedDB/types';
7
- import type { IDBController } from './indexedDB/dbController';
8
- export type { IndexedDBConfig, IDBController } from './indexedDB';
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,4 +1,4 @@
1
- import { RefObject } from 'preact';
1
+ import { RefObject } from "preact";
2
2
  export type UseMutationObserverOptions = MutationObserverInit;
3
3
  /**
4
4
  * A Preact hook to observe DOM mutations using MutationObserver.
@@ -1,7 +1,7 @@
1
1
  /** Effective connection type from Network Information API */
2
- export type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';
2
+ export type EffectiveConnectionType = "slow-2g" | "2g" | "3g" | "4g";
3
3
  /** Network connection type (e.g., wifi, cellular) */
4
- export type ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi';
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 = 'light' | 'dark' | 'no-preference';
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
@@ -1,4 +1,4 @@
1
- import type { RefObject } from 'preact';
1
+ import type { RefObject } from "preact";
2
2
  export interface RageClickPayload {
3
3
  /** Number of clicks that triggered the rage click */
4
4
  count: number;
@@ -1,4 +1,4 @@
1
- export type ThreadedWorkerMode = 'sequential' | 'parallel';
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;
@@ -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(): [startTransition: (callback: () => void) => void, isPending: boolean];
5
+ export declare function useTransition(): [
6
+ startTransition: (callback: () => void) => void,
7
+ isPending: boolean
8
+ ];
@@ -0,0 +1,57 @@
1
+ /**
2
+ * useWorkerNotifications – listen to worker messages and maintain running state, counts, history, and derived stats.
3
+ * @module useWorkerNotifications
4
+ */
5
+ /** Supported worker event types for tracking. Worker should postMessage with these shapes. */
6
+ export type WorkerEventType = "task_start" | "task_end" | "task_fail" | "queue_size";
7
+ export interface WorkerNotificationEvent {
8
+ type: WorkerEventType;
9
+ taskId?: string;
10
+ duration?: number;
11
+ error?: string;
12
+ size?: number;
13
+ timestamp: number;
14
+ }
15
+ export interface UseWorkerNotificationsOptions {
16
+ /** Max events to keep in history. Default 100. */
17
+ maxHistory?: number;
18
+ /** Window in ms for throughput calculation (completed per second). Default 1000. */
19
+ throughputWindowMs?: number;
20
+ }
21
+ export interface UseWorkerNotificationsReturn {
22
+ /** Task IDs currently running (received task_start, not yet task_end/task_fail). */
23
+ runningTasks: string[];
24
+ /** Total tasks that completed successfully. */
25
+ completedCount: number;
26
+ /** Total tasks that failed. */
27
+ failedCount: number;
28
+ /** Recent events (oldest first), capped at maxHistory. */
29
+ eventHistory: WorkerNotificationEvent[];
30
+ /** Average task duration in ms (from task_end events that include duration). */
31
+ averageDurationMs: number;
32
+ /** Completed tasks per second over the throughput window. */
33
+ throughputPerSecond: number;
34
+ /** Last reported queue size (from queue_size events); 0 if never sent. */
35
+ currentQueueSize: number;
36
+ /** Default view: all active worker data and progress in one object. */
37
+ progress: {
38
+ runningTasks: string[];
39
+ completedCount: number;
40
+ failedCount: number;
41
+ averageDurationMs: number;
42
+ throughputPerSecond: number;
43
+ currentQueueSize: number;
44
+ totalProcessed: number;
45
+ recentEventCount: number;
46
+ };
47
+ }
48
+ /**
49
+ * Listens to a Worker's messages and maintains state: running tasks, completed/failed counts,
50
+ * event history, execution time per task, average duration, throughput per second, and queue size.
51
+ * Worker should postMessage with: { type: 'task_start'|'task_end'|'task_fail'|'queue_size', taskId?, duration?, error?, size? }.
52
+ *
53
+ * @param worker - The Worker instance to listen to, or null/undefined to listen to nothing.
54
+ * @param options - Optional maxHistory and throughputWindowMs.
55
+ * @returns State and derived stats plus a default progress object.
56
+ */
57
+ export declare function useWorkerNotifications(worker: Worker | null | undefined, options?: UseWorkerNotificationsOptions): UseWorkerNotificationsReturn;
@@ -1,5 +1,5 @@
1
- import { ComponentChildren } from 'preact';
2
- export type InjectableProps = Record<string, any>;
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?: 'override' | 'preserve'): ComponentChildren;
10
+ export declare function useWrappedChildren(children: ComponentChildren, injectProps: InjectableProps, mergeStrategy?: "override" | "preserve"): ComponentChildren;
@@ -230,6 +230,62 @@
230
230
  color: var(--textMuted);
231
231
  font-size: 0.75rem;
232
232
  }
233
+ /* Worker notifications toasts */
234
+ .worker-toast-container {
235
+ position: fixed;
236
+ bottom: 1rem;
237
+ right: 1rem;
238
+ z-index: 9999;
239
+ display: flex;
240
+ flex-direction: column;
241
+ gap: 0.5rem;
242
+ max-width: 320px;
243
+ pointer-events: none;
244
+ }
245
+ .worker-toast {
246
+ padding: 0.5rem 0.75rem;
247
+ border-radius: var(--radiusSm);
248
+ font-size: 0.85rem;
249
+ font-weight: 500;
250
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
251
+ border: 1px solid;
252
+ animation: worker-toast-in 0.25s ease-out;
253
+ }
254
+ .worker-toast.running {
255
+ background: rgba(59, 130, 246, 0.2);
256
+ border-color: #3b82f6;
257
+ color: #93c5fd;
258
+ }
259
+ .worker-toast.queued {
260
+ background: rgba(245, 158, 11, 0.2);
261
+ border-color: var(--amber);
262
+ color: #fcd34d;
263
+ }
264
+ .worker-toast.completed {
265
+ background: var(--greenDim);
266
+ border-color: var(--green);
267
+ color: #86efac;
268
+ }
269
+ .worker-toast.failed {
270
+ background: rgba(239, 68, 68, 0.2);
271
+ border-color: var(--red);
272
+ color: #fca5a5;
273
+ }
274
+ .worker-toast.queue-update {
275
+ background: var(--surface2);
276
+ border-color: var(--border);
277
+ color: var(--textMuted);
278
+ }
279
+ @keyframes worker-toast-in {
280
+ from {
281
+ opacity: 0;
282
+ transform: translateX(100%);
283
+ }
284
+ to {
285
+ opacity: 1;
286
+ transform: translateX(0);
287
+ }
288
+ }
233
289
  </style>
234
290
  </head>
235
291
  <body>