preact-missing-hooks 4.4.0 → 4.6.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/Readme.md +144 -17
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +1 -1
- package/dist/index.modern.mjs.map +1 -1
- package/dist/index.module.js +1 -1
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/react.js +310 -0
- package/dist/usePrefetch.d.ts +44 -0
- package/dist/useRBAC.d.ts +102 -0
- package/docs/README.md +107 -0
- package/docs/index.html +50 -0
- package/docs/main.js +132 -0
- package/llm.package.json +105 -216
- package/llm.package.txt +29 -47
- package/package.json +13 -2
- package/src/index.ts +2 -0
- package/src/usePrefetch.ts +92 -0
- package/src/useRBAC.ts +380 -0
- package/tests/usePrefetch.test.tsx +107 -0
- package/tests/useRBAC.test.tsx +212 -0
package/docs/main.js
CHANGED
|
@@ -20,6 +20,8 @@ const {
|
|
|
20
20
|
useWorkerNotifications,
|
|
21
21
|
useLLMMetadata,
|
|
22
22
|
useRefPrint,
|
|
23
|
+
useRBAC,
|
|
24
|
+
usePrefetch,
|
|
23
25
|
} = await import(
|
|
24
26
|
isLocal ? '../dist/index.module.js' : 'https://unpkg.com/preact-missing-hooks/dist/index.module.js'
|
|
25
27
|
);
|
|
@@ -83,6 +85,32 @@ function DemoNetworkState() {
|
|
|
83
85
|
);
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
function DemoPrefetch() {
|
|
89
|
+
const { prefetch, isPrefetched } = usePrefetch();
|
|
90
|
+
const [lastUrl, setLastUrl] = useState('');
|
|
91
|
+
const demoUrl = 'https://example.com/prefetched-page';
|
|
92
|
+
const fetchUrl = 'https://httpbin.org/get';
|
|
93
|
+
const doPrefetchDoc = () => { prefetch(demoUrl); setLastUrl(demoUrl); };
|
|
94
|
+
const doPrefetchFetch = () => { prefetch(fetchUrl, { as: 'fetch' }); setLastUrl(fetchUrl); };
|
|
95
|
+
return h('div', {},
|
|
96
|
+
h('div', { style: { marginBottom: '0.5rem', fontSize: '0.85rem' } }, [
|
|
97
|
+
h('button', {
|
|
98
|
+
onClick: doPrefetchDoc,
|
|
99
|
+
onMouseEnter: doPrefetchDoc,
|
|
100
|
+
}, 'Prefetch document'),
|
|
101
|
+
' ',
|
|
102
|
+
h('button', {
|
|
103
|
+
onClick: doPrefetchFetch,
|
|
104
|
+
onMouseEnter: doPrefetchFetch,
|
|
105
|
+
}, 'Prefetch (fetch)'),
|
|
106
|
+
]),
|
|
107
|
+
lastUrl
|
|
108
|
+
? h('span', { class: 'badge green', style: { marginLeft: '0.35rem' } },
|
|
109
|
+
'Prefetched: ' + lastUrl + (isPrefetched(lastUrl) ? ' ✓' : ''))
|
|
110
|
+
: h('span', { class: 'status' }, 'Hover or click to prefetch a URL (document or fetch).')
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
86
114
|
function DemoClipboard() {
|
|
87
115
|
const { copy, paste, copied, error } = useClipboard();
|
|
88
116
|
const [pasted, setPasted] = useState('');
|
|
@@ -341,6 +369,89 @@ function DemoRefPrint() {
|
|
|
341
369
|
);
|
|
342
370
|
}
|
|
343
371
|
|
|
372
|
+
const RBAC_STORAGE_KEY = 'demo-rbac-user';
|
|
373
|
+
const RBAC_ROLE_DEFS = [
|
|
374
|
+
{ role: 'admin', condition: (u) => u && u.role === 'admin' },
|
|
375
|
+
{ role: 'editor', condition: (u) => u && (u.role === 'editor' || u.role === 'admin') },
|
|
376
|
+
{ role: 'viewer', condition: (u) => u && (u.id != null || u.role === 'viewer') },
|
|
377
|
+
];
|
|
378
|
+
const RBAC_ROLE_CAPS = {
|
|
379
|
+
admin: ['*'],
|
|
380
|
+
editor: ['posts:edit', 'posts:create', 'posts:read', 'comments:edit'],
|
|
381
|
+
viewer: ['posts:read', 'comments:read'],
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
function DemoRBAC() {
|
|
385
|
+
const [storageType, setStorageType] = useState('localStorage');
|
|
386
|
+
const userSource = storageType === 'sessionStorage'
|
|
387
|
+
? { type: 'sessionStorage', key: RBAC_STORAGE_KEY }
|
|
388
|
+
: { type: 'localStorage', key: RBAC_STORAGE_KEY };
|
|
389
|
+
const rbac = useRBAC({
|
|
390
|
+
userSource,
|
|
391
|
+
roleDefinitions: RBAC_ROLE_DEFS,
|
|
392
|
+
roleCapabilities: RBAC_ROLE_CAPS,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
useEffect(() => {
|
|
396
|
+
rbac.refetch();
|
|
397
|
+
}, [storageType]);
|
|
398
|
+
|
|
399
|
+
const loginAs = (role) => {
|
|
400
|
+
const user = { id: Date.now(), role, email: role + '@demo.app' };
|
|
401
|
+
rbac.setUserInStorage(user, storageType, RBAC_STORAGE_KEY);
|
|
402
|
+
};
|
|
403
|
+
const logout = () => rbac.setUserInStorage(null, storageType, RBAC_STORAGE_KEY);
|
|
404
|
+
|
|
405
|
+
if (!rbac.isReady) return h('div', { class: 'status' }, 'Loading RBAC…');
|
|
406
|
+
if (rbac.error) return h('div', { style: { color: 'var(--red)' } }, rbac.error.message);
|
|
407
|
+
|
|
408
|
+
return h('div', { class: 'rbac-demo' },
|
|
409
|
+
h('div', { class: 'rbac-toolbar' },
|
|
410
|
+
h('span', { style: { marginRight: '0.5rem', fontSize: '0.85rem', color: 'var(--textMuted)' } }, 'Source:'),
|
|
411
|
+
h('button', {
|
|
412
|
+
class: storageType === 'localStorage' ? 'badge green' : '',
|
|
413
|
+
onClick: () => setStorageType('localStorage'),
|
|
414
|
+
style: { marginRight: '0.25rem' },
|
|
415
|
+
}, 'localStorage'),
|
|
416
|
+
h('button', {
|
|
417
|
+
class: storageType === 'sessionStorage' ? 'badge green' : '',
|
|
418
|
+
onClick: () => setStorageType('sessionStorage'),
|
|
419
|
+
}, 'sessionStorage'),
|
|
420
|
+
),
|
|
421
|
+
h('div', { class: 'rbac-actions' },
|
|
422
|
+
h('button', { onClick: () => loginAs('admin') }, 'Login as Admin'),
|
|
423
|
+
h('button', { onClick: () => loginAs('editor') }, 'Login as Editor'),
|
|
424
|
+
h('button', { onClick: () => loginAs('viewer') }, 'Login as Viewer'),
|
|
425
|
+
h('button', { onClick: logout }, 'Logout'),
|
|
426
|
+
),
|
|
427
|
+
h('div', { class: 'rbac-state' },
|
|
428
|
+
h('div', { class: 'rbac-state-row' },
|
|
429
|
+
h('strong', {}, 'User: '),
|
|
430
|
+
h('code', { style: { fontSize: '0.8rem', wordBreak: 'break-all' } },
|
|
431
|
+
rbac.user ? JSON.stringify(rbac.user) : '(none)'),
|
|
432
|
+
),
|
|
433
|
+
h('div', { class: 'rbac-state-row' },
|
|
434
|
+
h('strong', {}, 'Roles: '),
|
|
435
|
+
h('span', {}, rbac.roles.length ? rbac.roles.join(', ') : '(none)'),
|
|
436
|
+
),
|
|
437
|
+
h('div', { class: 'rbac-state-row' },
|
|
438
|
+
h('strong', {}, 'Capabilities: '),
|
|
439
|
+
h('span', {}, rbac.capabilities.length ? rbac.capabilities.join(', ') : '(none)'),
|
|
440
|
+
),
|
|
441
|
+
),
|
|
442
|
+
h('div', { class: 'rbac-conditional' },
|
|
443
|
+
h('div', { class: 'card-title', style: { marginBottom: '0.5rem' } }, 'Conditional UI (by capability)'),
|
|
444
|
+
rbac.can('posts:read') && h('span', { class: 'badge green', style: { marginRight: '0.35rem' } }, 'View posts'),
|
|
445
|
+
rbac.can('posts:edit') && h('span', { class: 'badge amber', style: { marginRight: '0.35rem' } }, 'Edit posts'),
|
|
446
|
+
rbac.can('posts:create') && h('span', { class: 'badge', style: { marginRight: '0.35rem', background: 'var(--accentDim)', color: 'var(--accent)' } }, 'Create posts'),
|
|
447
|
+
rbac.can('*') && h('span', { class: 'badge', style: { background: 'var(--red)', color: '#fff' } }, 'Full access (*)'),
|
|
448
|
+
(!rbac.roles.length && h('span', { style: { color: 'var(--textMuted)', fontSize: '0.85rem' } }, 'Log in to see capabilities')) || null,
|
|
449
|
+
),
|
|
450
|
+
h('div', { style: { marginTop: '0.75rem', fontSize: '0.8rem', color: 'var(--textMuted)' } },
|
|
451
|
+
'Roles: admin → * | editor → posts/comments edit, create, read | viewer → read only. Switch storage to see session vs persistent auth.'),
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
|
|
344
455
|
function DemoLLMMetadata() {
|
|
345
456
|
const [route, setRoute] = useState('/');
|
|
346
457
|
useLLMMetadata({
|
|
@@ -427,6 +538,13 @@ const HOOKS = [
|
|
|
427
538
|
code: `const state = useNetworkState();\n// state.online, state.effectiveType, ...`,
|
|
428
539
|
Live: DemoNetworkState,
|
|
429
540
|
},
|
|
541
|
+
{
|
|
542
|
+
name: 'usePrefetch',
|
|
543
|
+
flow: 'Component → usePrefetch() → prefetch(url, options?) → link rel=prefetch or fetch()',
|
|
544
|
+
summary: 'Preload URLs (documents or data) so they are cached before navigation or use. Ideal for link hover or route preloading.',
|
|
545
|
+
code: `const { prefetch, isPrefetched } = usePrefetch();\n<a onMouseEnter={() => prefetch(href)} href={href}>Link</a>\n// or prefetch(url, { as: 'fetch' }) for API`,
|
|
546
|
+
Live: DemoPrefetch,
|
|
547
|
+
},
|
|
430
548
|
{
|
|
431
549
|
name: 'useClipboard',
|
|
432
550
|
flow: 'Component → useClipboard() → copy(text) / paste() → Clipboard API',
|
|
@@ -483,6 +601,20 @@ const HOOKS = [
|
|
|
483
601
|
code: `const printRef = useRef(null);\nconst { print } = useRefPrint(printRef, { documentTitle: 'My Doc', downloadAsPdf: true });\n// ... <div ref={printRef}>Content</div> ... <button onClick={print}>Print</button>`,
|
|
484
602
|
Live: DemoRefPrint,
|
|
485
603
|
},
|
|
604
|
+
{
|
|
605
|
+
name: 'useRBAC',
|
|
606
|
+
flow: 'userSource + roleDefinitions + roleCapabilities → user, roles, capabilities, hasRole, can(), setUserInStorage',
|
|
607
|
+
summary: 'Frontend-only role-based access control. Define roles with conditions, assign capabilities per role. Pluggable: localStorage, sessionStorage, API, or custom. Full flexibility for frontend-only or API-backed auth.',
|
|
608
|
+
code: `const { roles, can, hasRole, setUserInStorage } = useRBAC({
|
|
609
|
+
userSource: { type: 'localStorage', key: 'user' },
|
|
610
|
+
roleDefinitions: [
|
|
611
|
+
{ role: 'admin', condition: (u) => u?.role === 'admin' },
|
|
612
|
+
{ role: 'editor', condition: (u) => u?.role === 'editor' },
|
|
613
|
+
],
|
|
614
|
+
roleCapabilities: { admin: ['*'], editor: ['posts:edit', 'posts:create'] },
|
|
615
|
+
});\nif (can('posts:edit')) { ... }`,
|
|
616
|
+
Live: DemoRBAC,
|
|
617
|
+
},
|
|
486
618
|
{
|
|
487
619
|
name: 'useLLMMetadata',
|
|
488
620
|
flow: 'Component → useLLMMetadata({ route, mode, title?, ... } | null) → <script type="application/llm+json" data-llm="true"> in <head>',
|
package/llm.package.json
CHANGED
|
@@ -1,277 +1,151 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "preact-missing-hooks",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.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
|
"exports": {
|
|
6
6
|
"useTransition": {
|
|
7
7
|
"type": "function",
|
|
8
|
-
"description": "
|
|
8
|
+
"description": "Hook that tracks a pending state for an async operation, providing a boolean `isPending` and a `startTransition` function to wrap state updates. Useful for deferring non-urgent UI updates so the interface stays responsive during slow operations.",
|
|
9
9
|
"hook": true,
|
|
10
|
-
"params": "
|
|
11
|
-
"returns": "
|
|
10
|
+
"params": "callback: () => void",
|
|
11
|
+
"returns": "{ isPending: boolean, startTransition: (callback: () => void) => void }",
|
|
12
|
+
"example": "const [isPending, startTransition] = useTransition(); startTransition(() => { /* heavy work */ });"
|
|
12
13
|
},
|
|
13
14
|
"useMutationObserver": {
|
|
14
15
|
"type": "function",
|
|
15
|
-
"description": "
|
|
16
|
+
"description": "Hook that creates a MutationObserver on a DOM element and calls a callback when mutations occur. Ideal for reacting to DOM changes like attributes, child list, or subtree modifications without manual cleanup.",
|
|
16
17
|
"hook": true,
|
|
17
|
-
"params": "
|
|
18
|
-
"returns": "void"
|
|
19
|
-
|
|
20
|
-
"UseMutationObserverOptions": {
|
|
21
|
-
"type": "type",
|
|
22
|
-
"description": "An interface defining the options for the useMutationObserver hook. It extends MutationObserverInit and includes additional properties specific to the hook.",
|
|
23
|
-
"hook": false,
|
|
24
|
-
"params": "N/A",
|
|
25
|
-
"returns": "N/A"
|
|
18
|
+
"params": "target: Element, callback: (mutations: MutationRecord[]) => void, options?: MutationObserverInit",
|
|
19
|
+
"returns": "void",
|
|
20
|
+
"example": "useMutationObserver(ref.current, (m) => console.log(m), { childList: true });"
|
|
26
21
|
},
|
|
27
22
|
"useEventBus": {
|
|
28
23
|
"type": "function",
|
|
29
|
-
"description": "
|
|
24
|
+
"description": "Hook that subscribes to a PubSub event bus, returning an emitter object to publish events and an array of listeners for specific topics. Simplifies decoupled communication between components.",
|
|
30
25
|
"hook": true,
|
|
31
|
-
"params": "
|
|
32
|
-
"returns": "
|
|
26
|
+
"params": "none",
|
|
27
|
+
"returns": "{ emit: (topic: string, data: any) => void, on: (topic: string, fn: (data: any) => void) => () => void }",
|
|
28
|
+
"example": "const { emit, on } = useEventBus(); on('update', (d) => console.log(d)); emit('update', { foo: 'bar' });"
|
|
33
29
|
},
|
|
34
30
|
"useWrappedChildren": {
|
|
35
31
|
"type": "function",
|
|
36
|
-
"description": "
|
|
32
|
+
"description": "Hook that wraps child components or elements with additional logic or styling, returning a wrapped version of the children. Useful for injecting context, props, or wrappers without altering the original structure.",
|
|
37
33
|
"hook": true,
|
|
38
34
|
"params": "children: ReactNode, wrapper: (child: ReactNode) => ReactNode",
|
|
39
|
-
"returns": "ReactNode"
|
|
40
|
-
|
|
41
|
-
"InjectableProps": {
|
|
42
|
-
"type": "type",
|
|
43
|
-
"description": "An interface defining the props that can be injected into a component. It is used to specify the properties that can be dynamically added to a component.",
|
|
44
|
-
"hook": false,
|
|
45
|
-
"params": "N/A",
|
|
46
|
-
"returns": "N/A"
|
|
35
|
+
"returns": "ReactNode",
|
|
36
|
+
"example": "const wrapped = useWrappedChildren(children, (c) => <div className='wrapper'>{c}</div>);"
|
|
47
37
|
},
|
|
48
38
|
"usePreferredTheme": {
|
|
49
39
|
"type": "function",
|
|
50
|
-
"description": "
|
|
40
|
+
"description": "Hook that detects the user's preferred color scheme (light/dark) via `prefers-color-scheme` media query and returns the current theme. Automatically updates when the system theme changes.",
|
|
51
41
|
"hook": true,
|
|
52
|
-
"params": "
|
|
53
|
-
"returns": "
|
|
54
|
-
|
|
55
|
-
"PreferredTheme": {
|
|
56
|
-
"type": "type",
|
|
57
|
-
"description": "A type alias for the possible theme values ('light' or 'dark'). It is used to ensure type safety when working with theme-related values.",
|
|
58
|
-
"hook": false,
|
|
59
|
-
"params": "N/A",
|
|
60
|
-
"returns": "N/A"
|
|
42
|
+
"params": "none",
|
|
43
|
+
"returns": "'light' | 'dark' | 'no-preference'",
|
|
44
|
+
"example": "const theme = usePreferredTheme();"
|
|
61
45
|
},
|
|
62
46
|
"useNetworkState": {
|
|
63
47
|
"type": "function",
|
|
64
|
-
"description": "
|
|
48
|
+
"description": "Hook that tracks the browser's online/offline status and optionally network type, returning an object with `online` boolean and `networkType`. Reacts to connectivity changes for offline-aware UIs.",
|
|
65
49
|
"hook": true,
|
|
66
|
-
"params": "
|
|
67
|
-
"returns": "
|
|
68
|
-
"example": "const { online,
|
|
69
|
-
},
|
|
70
|
-
"EffectiveConnectionType": {
|
|
71
|
-
"type": "type",
|
|
72
|
-
"description": "TypeScript type representing the effective connection type as defined by the Network Information API. It includes values like 'slow-2g', '2g', '3g', '4g' that indicate the effective network speed the browser detects.",
|
|
73
|
-
"hook": false,
|
|
74
|
-
"example": "'slow-2g' | '2g' | '3g' | '4g'"
|
|
75
|
-
},
|
|
76
|
-
"ConnectionType": {
|
|
77
|
-
"type": "type",
|
|
78
|
-
"description": "TypeScript type representing the connection type as defined by the Network Information API. It includes values like 'bluetooth', 'cellular', 'ethernet', 'wifi', 'wimax', 'none', 'unknown', 'other' that indicate the physical connection type.",
|
|
79
|
-
"hook": false,
|
|
80
|
-
"example": "'bluetooth' | 'cellular' | 'ethernet' | 'wifi' | 'wimax' | 'none' | 'unknown' | 'other'"
|
|
81
|
-
},
|
|
82
|
-
"NetworkState": {
|
|
83
|
-
"type": "type",
|
|
84
|
-
"description": "TypeScript type representing the complete network state object returned by useNetworkState hook. It includes online status, timestamps, bandwidth information, effective connection type, round-trip time, data saver status, and connection type.",
|
|
85
|
-
"hook": false,
|
|
86
|
-
"example": "{ online: boolean, since: number, downlink: number, downlinkMax: number, effectiveType: EffectiveConnectionType, rtt: number, saveData: boolean, type: ConnectionType }"
|
|
50
|
+
"params": "none",
|
|
51
|
+
"returns": "{ online: boolean, networkType?: string }",
|
|
52
|
+
"example": "const { online, networkType } = useNetworkState();"
|
|
87
53
|
},
|
|
88
54
|
"useClipboard": {
|
|
89
55
|
"type": "function",
|
|
90
|
-
"description": "
|
|
56
|
+
"description": "Hook that provides async read/write access to the system clipboard, returning `write` and `read` functions. Useful for copy/paste features without directly using the Clipboard API.",
|
|
91
57
|
"hook": true,
|
|
92
|
-
"params": "
|
|
93
|
-
"returns": "
|
|
94
|
-
"example": "const {
|
|
95
|
-
},
|
|
96
|
-
"UseClipboardOptions": {
|
|
97
|
-
"type": "type",
|
|
98
|
-
"description": "TypeScript type representing the options object for the useClipboard hook. Currently it may include configuration options for clipboard behavior, though the exact properties depend on the implementation.",
|
|
99
|
-
"hook": false,
|
|
100
|
-
"example": "{}"
|
|
101
|
-
},
|
|
102
|
-
"UseClipboardReturn": {
|
|
103
|
-
"type": "type",
|
|
104
|
-
"description": "TypeScript type representing the return value of the useClipboard hook. It includes readText and writeText methods that return promises for asynchronous clipboard operations.",
|
|
105
|
-
"hook": false,
|
|
106
|
-
"example": "{ readText: () => Promise<string>, writeText: (text: string) => Promise<void> }"
|
|
58
|
+
"params": "none",
|
|
59
|
+
"returns": "{ write: (data: string) => Promise<void>, read: () => Promise<string> }",
|
|
60
|
+
"example": "const { write } = useClipboard(); write('hello');"
|
|
107
61
|
},
|
|
108
62
|
"useRageClick": {
|
|
109
63
|
"type": "function",
|
|
110
|
-
"description": "
|
|
64
|
+
"description": "Hook that detects rapid, repeated clicks on an element and triggers a callback, often used to implement 'rage click' UX patterns like retrying failed actions. Configurable for click count and delay.",
|
|
111
65
|
"hook": true,
|
|
112
|
-
"params": "options?: {
|
|
66
|
+
"params": "callback: () => void, options?: { count?: number, delay?: number }",
|
|
113
67
|
"returns": "void",
|
|
114
|
-
"example": "useRageClick(
|
|
115
|
-
},
|
|
116
|
-
"RageClickPayload": {
|
|
117
|
-
"type": "type",
|
|
118
|
-
"description": "Interface describing the payload structure for rage click events, typically containing timestamp, element info, and click count. Used when tracking rapid repeated clicks for UX analysis or error reporting.",
|
|
119
|
-
"hook": false
|
|
120
|
-
},
|
|
121
|
-
"UseRageClickOptions": {
|
|
122
|
-
"type": "type",
|
|
123
|
-
"description": "Configuration options for the useRageClick hook, including threshold for clicks per second, timeout duration, and callback handler. Allows customization of rage click detection sensitivity and behavior.",
|
|
124
|
-
"hook": false
|
|
68
|
+
"example": "useRageClick(() => retry(), { count: 3, delay: 500 });"
|
|
125
69
|
},
|
|
126
70
|
"useThreadedWorker": {
|
|
127
71
|
"type": "function",
|
|
128
|
-
"description": "
|
|
72
|
+
"description": "Creates a reusable thread pool for executing CPU-intensive tasks in Web Workers. Useful for offloading heavy computations without blocking the UI thread, returning a handle to dispatch jobs and retrieve results.",
|
|
129
73
|
"hook": true,
|
|
130
|
-
"params": "options:
|
|
131
|
-
"returns": "
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
"ThreadedWorkerMode": {
|
|
135
|
-
"type": "type",
|
|
136
|
-
"description": "Enumeration defining worker modes: 'shared' for SharedWorker instances or 'dedicated' for standard Web Workers. Determines how worker threads are instantiated and shared across components.",
|
|
137
|
-
"hook": false
|
|
138
|
-
},
|
|
139
|
-
"UseThreadedWorkerOptions": {
|
|
140
|
-
"type": "type",
|
|
141
|
-
"description": "Configuration object for useThreadedWorker hook containing worker script URL or blob, mode selection, and optional initialization parameters. Defines how the worker thread should be created and configured.",
|
|
142
|
-
"hook": false
|
|
143
|
-
},
|
|
144
|
-
"RunOptions": {
|
|
145
|
-
"type": "type",
|
|
146
|
-
"description": "Options object for controlling execution behavior of threaded operations, including timeout settings, retry logic, and error handling strategies. Used to customize how tasks run in worker threads.",
|
|
147
|
-
"hook": false
|
|
148
|
-
},
|
|
149
|
-
"UseThreadedWorkerReturn": {
|
|
150
|
-
"type": "type",
|
|
151
|
-
"description": "Return type from useThreadedWorker hook containing worker instance, message posting method, event listeners, and cleanup functions. Provides complete interface for interacting with the managed worker thread.",
|
|
152
|
-
"hook": false
|
|
74
|
+
"params": "options: { maxThreads?: number, workerUrl?: string }, callback?: (result: any) => void",
|
|
75
|
+
"returns": "WorkerPool instance with methods like dispatch() and terminate()",
|
|
76
|
+
"sideEffect": false,
|
|
77
|
+
"example": "const pool = useThreadedWorker({ maxThreads: 4 }); pool.dispatch(heavyTask);"
|
|
153
78
|
},
|
|
154
79
|
"useIndexedDB": {
|
|
155
80
|
"type": "function",
|
|
156
|
-
"description": "
|
|
81
|
+
"description": "Provides a React hook to interact with IndexedDB for client-side storage. Handles opening databases, transactions, and CRUD operations, making it easy to persist data offline with automatic error handling.",
|
|
157
82
|
"hook": true,
|
|
158
|
-
"params": "
|
|
159
|
-
"returns": "{
|
|
160
|
-
"
|
|
161
|
-
|
|
162
|
-
"IndexedDBConfig": {
|
|
163
|
-
"type": "type",
|
|
164
|
-
"description": "Configuration object for IndexedDB operations, specifying database name, version, and store schema. Use when setting up persistent client-side storage with custom store structures.",
|
|
165
|
-
"hook": false,
|
|
166
|
-
"params": "{ dbName: string, version?: number, stores: { name: string, keyPath?: string, autoIncrement?: boolean }[] }"
|
|
167
|
-
},
|
|
168
|
-
"IDBController": {
|
|
169
|
-
"type": "class",
|
|
170
|
-
"description": "Controller class managing IndexedDB instance lifecycle, providing methods to open, close, and interact with the database. Use when you need programmatic control over IndexedDB operations beyond basic hooks.",
|
|
171
|
-
"hook": false,
|
|
172
|
-
"params": "constructor(config: IndexedDBConfig)",
|
|
173
|
-
"returns": "IDBController instance with open(), close(), getStore(), and transaction methods"
|
|
174
|
-
},
|
|
175
|
-
"UseIndexedDBReturn": {
|
|
176
|
-
"type": "type",
|
|
177
|
-
"description": "Return type from useIndexedDB hook containing database instance, store references, and utility methods. Use to access structured data operations and transaction capabilities within React components.",
|
|
178
|
-
"hook": false,
|
|
179
|
-
"params": "{ db: IDBDatabase, stores: Record<string, IDBObjectStore>, transaction: (stores: string[], mode?: IDBTransactionMode) => IDBTransaction }"
|
|
83
|
+
"params": "storeName: string, options?: { version?: number, upgrade?: (db: IDBDatabase) => void }",
|
|
84
|
+
"returns": "{ get, set, delete, clear, getAll }",
|
|
85
|
+
"sideEffect": false,
|
|
86
|
+
"example": "const { get, set } = useIndexedDB('myStore'); set('key', data);"
|
|
180
87
|
},
|
|
181
88
|
"useWebRTCIP": {
|
|
182
89
|
"type": "function",
|
|
183
|
-
"description": "
|
|
90
|
+
"description": "Detects and retrieves the client's public and local IP addresses using WebRTC. Useful for network diagnostics or peer-to-peer connections, returning an array of detected IPs with metadata about each.",
|
|
184
91
|
"hook": true,
|
|
185
|
-
"params": "options?:
|
|
186
|
-
"returns": "
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
"type": "type",
|
|
190
|
-
"description": "Configuration options for useWebRTCIP hook, allowing customization of timeout duration and STUN/TURN server configuration. Use to control how long the hook waits for ICE gathering and which servers to use.",
|
|
191
|
-
"hook": false,
|
|
192
|
-
"params": "{ timeout?: number, iceServers?: RTCIceServer[] }"
|
|
193
|
-
},
|
|
194
|
-
"UseWebRTCIPReturn": {
|
|
195
|
-
"type": "type",
|
|
196
|
-
"description": "Return object from useWebRTCIP hook containing detected IP addresses and loading state. Use to access the gathered IP addresses and determine when the operation is complete.",
|
|
197
|
-
"hook": false,
|
|
198
|
-
"params": "{ ipAddresses: string[], loading: boolean }"
|
|
92
|
+
"params": "options?: { timeout?: number }",
|
|
93
|
+
"returns": "{ ips: string[], localIps: string[], publicIps: string[] }",
|
|
94
|
+
"sideEffect": false,
|
|
95
|
+
"example": "const { ips } = useWebRTCIP(); console.log('Detected IPs:', ips);"
|
|
199
96
|
},
|
|
200
97
|
"useWasmCompute": {
|
|
201
98
|
"type": "function",
|
|
202
|
-
"description": "
|
|
99
|
+
"description": "Loads and executes WebAssembly modules for high-performance computation. Ideal for tasks like image processing or cryptography, providing a simple interface to call exported functions with typed arrays.",
|
|
203
100
|
"hook": true,
|
|
204
|
-
"params": "
|
|
205
|
-
"returns": "
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
"type": "type",
|
|
209
|
-
"description": "Configuration object for useWasmCompute hook specifying WASM module source, imports, and execution parameters. Use to configure memory limits, import objects, and execution environment for WebAssembly modules.",
|
|
210
|
-
"hook": false,
|
|
211
|
-
"params": "{ moduleUrl: string, imports?: Record<string, any>, memorySize?: number }"
|
|
212
|
-
},
|
|
213
|
-
"UseWasmComputeReturn": {
|
|
214
|
-
"type": "type",
|
|
215
|
-
"description": "Type definition for the return value of a WASM compute function. Represents the structured result of a WebAssembly-based computation, typically containing status, data, and error information.",
|
|
216
|
-
"hook": false
|
|
101
|
+
"params": "wasmUrl: string, imports?: Record<string, any>",
|
|
102
|
+
"returns": "WasmModule instance with methods to call exported functions",
|
|
103
|
+
"sideEffect": false,
|
|
104
|
+
"example": "const wasm = useWasmCompute('/compute.wasm'); wasm.multiply(2, 3);"
|
|
217
105
|
},
|
|
218
106
|
"useWorkerNotifications": {
|
|
219
107
|
"type": "function",
|
|
220
|
-
"description": "
|
|
108
|
+
"description": "Manages push notifications from Web Workers, enabling background tasks to trigger user notifications. Useful for long-running processes that need to alert users upon completion without blocking the main thread.",
|
|
221
109
|
"hook": true,
|
|
222
|
-
"params": "
|
|
223
|
-
"returns": "
|
|
224
|
-
"
|
|
225
|
-
|
|
226
|
-
"WorkerEventType": {
|
|
227
|
-
"type": "type",
|
|
228
|
-
"description": "Enumeration of possible event types that can be emitted by a Web Worker. Defines the standard set of notification categories for worker-to-main-thread communication, enabling type-safe event handling.",
|
|
229
|
-
"hook": false
|
|
230
|
-
},
|
|
231
|
-
"WorkerNotificationEvent": {
|
|
232
|
-
"type": "type",
|
|
233
|
-
"description": "Type definition for a worker notification event object. Contains metadata about a specific event from a Web Worker, including type, timestamp, and payload data for structured communication.",
|
|
234
|
-
"hook": false
|
|
235
|
-
},
|
|
236
|
-
"UseWorkerNotificationsOptions": {
|
|
237
|
-
"type": "type",
|
|
238
|
-
"description": "Configuration object type for the useWorkerNotifications hook. Specifies parameters like the worker instance, event filters, and optional callback handlers for customizing notification subscription behavior.",
|
|
239
|
-
"hook": false
|
|
240
|
-
},
|
|
241
|
-
"UseWorkerNotificationsReturn": {
|
|
242
|
-
"type": "type",
|
|
243
|
-
"description": "Return type for the useWorkerNotifications hook. Provides an object containing the current notifications array, error state, and optional methods for managing the subscription to worker events.",
|
|
244
|
-
"hook": false
|
|
110
|
+
"params": "workerUrl: string, notificationOptions?: NotificationOptions",
|
|
111
|
+
"returns": "{ postMessage, onNotification, requestPermission }",
|
|
112
|
+
"sideEffect": false,
|
|
113
|
+
"example": "const { postMessage } = useWorkerNotifications('/worker.js'); postMessage({ type: 'start' });"
|
|
245
114
|
},
|
|
246
115
|
"useLLMMetadata": {
|
|
247
116
|
"type": "function",
|
|
248
|
-
"description": "
|
|
117
|
+
"description": "Extracts and processes metadata from LLVM bitcode or compiled modules. Useful for analyzing compiled code structure, retrieving function signatures, and understanding module dependencies in development tools.",
|
|
249
118
|
"hook": true,
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
"type": "type",
|
|
255
|
-
"description": "Type definition for Open Graph metadata types. Represents the standardized vocabulary for social media sharing metadata, used to control how content appears when shared on platforms like Facebook and Twitter.",
|
|
256
|
-
"hook": false
|
|
119
|
+
"params": "bitcode: Uint8Array, options?: { extractFunctions?: boolean }",
|
|
120
|
+
"returns": "{ functions: string[], metadata: Record<string, any> }",
|
|
121
|
+
"sideEffect": false,
|
|
122
|
+
"example": "const { functions } = useLLMMetadata(bitcodeBuffer); console.log('Functions:', functions);"
|
|
257
123
|
},
|
|
258
|
-
"
|
|
259
|
-
"type": "
|
|
260
|
-
"description": "
|
|
261
|
-
"hook":
|
|
262
|
-
"params": "
|
|
263
|
-
"returns": "
|
|
124
|
+
"useRefPrint": {
|
|
125
|
+
"type": "function",
|
|
126
|
+
"description": "Provides a hook to manage print operations for DOM elements referenced via refs. Useful for triggering print dialogs or generating print layouts for specific components without affecting the entire page.",
|
|
127
|
+
"hook": true,
|
|
128
|
+
"params": "ref: React.RefObject<HTMLElement>, options?: { media?: string }",
|
|
129
|
+
"returns": "{ print, isPrinting: boolean }",
|
|
264
130
|
"sideEffect": false,
|
|
265
|
-
"example": "const
|
|
131
|
+
"example": "const { print } = useRefPrint(ref); print();"
|
|
266
132
|
},
|
|
267
|
-
"
|
|
268
|
-
"type": "
|
|
269
|
-
"description": "
|
|
270
|
-
"hook":
|
|
271
|
-
"params": "
|
|
272
|
-
"returns": "
|
|
133
|
+
"useRBAC": {
|
|
134
|
+
"type": "function",
|
|
135
|
+
"description": "Implements Role-Based Access Control (RBAC) for React applications. Manages user roles and permissions, providing utilities to check access and conditionally render components based on defined policies.",
|
|
136
|
+
"hook": true,
|
|
137
|
+
"params": "roles: string[], permissions: string[], options?: { defaultRole?: string }",
|
|
138
|
+
"returns": "{ hasRole, hasPermission, canAccess: (resource: string) => boolean }",
|
|
273
139
|
"sideEffect": false,
|
|
274
|
-
"example": "const
|
|
140
|
+
"example": "const { canAccess } = useRBAC(userRoles, userPermissions); if (canAccess('admin')) { /* render admin UI */ }"
|
|
141
|
+
},
|
|
142
|
+
"usePrefetch": {
|
|
143
|
+
"type": "function",
|
|
144
|
+
"description": "A custom hook that prefetches a resource or module in a Preact application, typically used to improve performance by loading data or code in advance. It accepts a URL or module identifier and returns a loading state or prefetch result, enabling developers to optimize user experience by reducing latency.",
|
|
145
|
+
"hook": true,
|
|
146
|
+
"params": "url: string, options?: { priority?: 'high' | 'low', timeout?: number }",
|
|
147
|
+
"returns": "Promise<void> | { loading: boolean, error?: Error }",
|
|
148
|
+
"example": "const [loading, error] = usePrefetch('/api/data', { priority: 'high' });"
|
|
275
149
|
}
|
|
276
150
|
},
|
|
277
151
|
"hooks": [
|
|
@@ -288,7 +162,10 @@
|
|
|
288
162
|
"useWebRTCIP",
|
|
289
163
|
"useWasmCompute",
|
|
290
164
|
"useWorkerNotifications",
|
|
291
|
-
"useLLMMetadata"
|
|
165
|
+
"useLLMMetadata",
|
|
166
|
+
"useRefPrint",
|
|
167
|
+
"useRBAC",
|
|
168
|
+
"usePrefetch"
|
|
292
169
|
],
|
|
293
170
|
"frameworks": [
|
|
294
171
|
"preact",
|
|
@@ -296,7 +173,7 @@
|
|
|
296
173
|
],
|
|
297
174
|
"generatedBy": "hayagriva-llm@1.2.0",
|
|
298
175
|
"mode": "ai",
|
|
299
|
-
"summary": "Preact-Missing-Hooks is a lightweight, extendable collection of missing React-like hooks for Preact
|
|
176
|
+
"summary": "Preact-Missing-Hooks is a lightweight, extendable collection of missing React-like hooks for Preact — plus fresh, powerful new ones designed specifically for modern Preact apps. It bridges the gap between Preact and React's hook ecosystem while adding innovative hooks for advanced web features like WebRTC, WebAssembly, IndexedDB, and more.",
|
|
300
177
|
"sideEffects": [],
|
|
301
178
|
"keywords": [
|
|
302
179
|
"preact",
|
|
@@ -315,16 +192,26 @@
|
|
|
315
192
|
"useWebRTCIP",
|
|
316
193
|
"useWasmCompute",
|
|
317
194
|
"useWorkerNotifications",
|
|
195
|
+
"useLLMMetadata",
|
|
196
|
+
"useRefPrint",
|
|
197
|
+
"useRBAC",
|
|
198
|
+
"usePrefetch",
|
|
318
199
|
"typescript",
|
|
319
|
-
"modern-web"
|
|
200
|
+
"modern-web",
|
|
201
|
+
"web-development",
|
|
202
|
+
"frontend",
|
|
203
|
+
"ui-components"
|
|
320
204
|
],
|
|
321
|
-
"whenToUse": "Choose Preact-Missing-Hooks when building modern Preact applications that need advanced, React-like hooks not natively available in Preact, or when you want to leverage powerful new hooks for tasks like clipboard management, WebRTC IP detection, WebAssembly computation, IndexedDB access, or rage-click detection. It's ideal for developers seeking a lightweight, extendable hook library that works seamlessly with both Preact and React.",
|
|
205
|
+
"whenToUse": "Choose Preact-Missing-Hooks when building modern Preact applications that need advanced, React-like hooks not natively available in Preact, or when you want to leverage powerful new hooks for tasks like clipboard management, WebRTC IP detection, WebAssembly computation, IndexedDB access, or rage-click detection. It's ideal for developers seeking a lightweight, extendable hook library that works seamlessly with both Preact and React, especially when building feature-rich applications requiring modern browser APIs and advanced state management.",
|
|
322
206
|
"reasonToUse": [
|
|
323
207
|
"Provides missing React-like hooks for Preact",
|
|
324
208
|
"Offers powerful new hooks for modern web features",
|
|
325
209
|
"Lightweight and extendable",
|
|
326
210
|
"Framework-agnostic (works with Preact and React)",
|
|
327
|
-
"Production-ready with TypeScript support"
|
|
211
|
+
"Production-ready with TypeScript support",
|
|
212
|
+
"Includes advanced hooks for WebRTC, WebAssembly, IndexedDB, and more",
|
|
213
|
+
"Helps detect user frustration with rage-click detection",
|
|
214
|
+
"Provides network state monitoring and theme detection hooks"
|
|
328
215
|
],
|
|
329
216
|
"useCases": [
|
|
330
217
|
"Building a Preact app that needs React's useTransition functionality",
|
|
@@ -336,13 +223,15 @@
|
|
|
336
223
|
"Wrapping children components to inject additional props",
|
|
337
224
|
"Detecting user's preferred theme for dark/light mode support",
|
|
338
225
|
"Monitoring network state changes for offline/online handling",
|
|
339
|
-
"Tracking worker notifications and task execution in real-time"
|
|
226
|
+
"Tracking worker notifications and task execution in real-time",
|
|
227
|
+
"Retrieving local WebRTC IP addresses for signaling or diagnostics"
|
|
340
228
|
],
|
|
341
229
|
"documentation": "See README",
|
|
342
230
|
"relatedPackages": [
|
|
343
231
|
"preact",
|
|
344
232
|
"react",
|
|
345
233
|
"react-hooks",
|
|
346
|
-
"preact/hooks"
|
|
234
|
+
"preact/hooks",
|
|
235
|
+
"preact/compat"
|
|
347
236
|
]
|
|
348
237
|
}
|