@affectively/aeon-pages-react 0.2.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/dist/Link.d.ts +37 -0
- package/dist/components/InstallPrompt.d.ts +59 -0
- package/dist/components/OfflineDiagnostics.d.ts +78 -0
- package/dist/components/PushNotifications.d.ts +70 -0
- package/dist/hooks/useAeonNavigation.d.ts +73 -0
- package/dist/hooks/useConflicts.d.ts +67 -0
- package/dist/hooks/useNetworkState.d.ts +36 -0
- package/dist/hooks/usePilotNavigation.d.ts +86 -0
- package/dist/hooks/useServiceWorker.d.ts +60 -0
- package/dist/hooks.d.ts +87 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +14837 -0
- package/dist/provider.d.ts +91 -0
- package/package.json +39 -0
package/dist/Link.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aeon Link Component
|
|
3
|
+
*
|
|
4
|
+
* Drop-in replacement for <a> with superpowers:
|
|
5
|
+
* - Visibility-based prefetch
|
|
6
|
+
* - Hover prefetch
|
|
7
|
+
* - Intent detection (cursor trajectory)
|
|
8
|
+
* - View transitions
|
|
9
|
+
* - Presence awareness
|
|
10
|
+
* - Total preload support
|
|
11
|
+
*/
|
|
12
|
+
import React, { type ReactNode, type AnchorHTMLAttributes } from 'react';
|
|
13
|
+
export type TransitionType = 'slide' | 'fade' | 'morph' | 'none';
|
|
14
|
+
export type PrefetchStrategy = 'hover' | 'visible' | 'intent' | 'none';
|
|
15
|
+
export interface PresenceRenderProps {
|
|
16
|
+
count: number;
|
|
17
|
+
editing: number;
|
|
18
|
+
hot: boolean;
|
|
19
|
+
users?: {
|
|
20
|
+
userId: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
export interface LinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> {
|
|
25
|
+
href: string;
|
|
26
|
+
prefetch?: PrefetchStrategy;
|
|
27
|
+
transition?: TransitionType;
|
|
28
|
+
showPresence?: boolean;
|
|
29
|
+
preloadData?: boolean;
|
|
30
|
+
replace?: boolean;
|
|
31
|
+
children?: ReactNode | ((props: {
|
|
32
|
+
presence: PresenceRenderProps | null;
|
|
33
|
+
}) => ReactNode);
|
|
34
|
+
onNavigateStart?: () => void;
|
|
35
|
+
onNavigateEnd?: () => void;
|
|
36
|
+
}
|
|
37
|
+
export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InstallPrompt Component
|
|
3
|
+
*
|
|
4
|
+
* PWA install prompt component for web applications.
|
|
5
|
+
* Handles beforeinstallprompt event and iOS-specific instructions.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Cross-browser install prompt handling
|
|
9
|
+
* - iOS-specific installation instructions
|
|
10
|
+
* - Standalone mode detection
|
|
11
|
+
* - Customizable UI via render props
|
|
12
|
+
* - Headless hook export
|
|
13
|
+
*/
|
|
14
|
+
import { type ReactNode } from 'react';
|
|
15
|
+
interface BeforeInstallPromptEvent extends Event {
|
|
16
|
+
prompt: () => Promise<void>;
|
|
17
|
+
userChoice: Promise<{
|
|
18
|
+
outcome: 'accepted' | 'dismissed';
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export interface InstallPromptState {
|
|
22
|
+
/** Whether the app can be installed */
|
|
23
|
+
canInstall: boolean;
|
|
24
|
+
/** Whether the app is already installed (standalone mode) */
|
|
25
|
+
isInstalled: boolean;
|
|
26
|
+
/** Whether on iOS */
|
|
27
|
+
isIOS: boolean;
|
|
28
|
+
/** Trigger the install prompt (Chrome/Edge) */
|
|
29
|
+
install: () => Promise<'accepted' | 'dismissed' | 'unavailable'>;
|
|
30
|
+
/** Dismiss the install prompt */
|
|
31
|
+
dismiss: () => void;
|
|
32
|
+
}
|
|
33
|
+
export interface InstallPromptProps {
|
|
34
|
+
/** Render when app is already installed */
|
|
35
|
+
renderInstalled?: () => ReactNode;
|
|
36
|
+
/** Render install prompt (receives install function) */
|
|
37
|
+
renderPrompt?: (state: InstallPromptState) => ReactNode;
|
|
38
|
+
/** Render iOS-specific instructions */
|
|
39
|
+
renderIOSInstructions?: () => ReactNode;
|
|
40
|
+
/** Only show when install is available */
|
|
41
|
+
showOnlyWhenInstallable?: boolean;
|
|
42
|
+
/** CSS class for container */
|
|
43
|
+
className?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Hook for managing PWA install prompt
|
|
47
|
+
*/
|
|
48
|
+
export declare function useInstallPrompt(): InstallPromptState;
|
|
49
|
+
/**
|
|
50
|
+
* PWA install prompt component
|
|
51
|
+
*/
|
|
52
|
+
export declare function InstallPrompt({ renderInstalled, renderPrompt, renderIOSInstructions, showOnlyWhenInstallable, className, }: InstallPromptProps): ReactNode;
|
|
53
|
+
declare global {
|
|
54
|
+
interface WindowEventMap {
|
|
55
|
+
beforeinstallprompt: BeforeInstallPromptEvent;
|
|
56
|
+
appinstalled: Event;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export default InstallPrompt;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OfflineDiagnostics Component
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive diagnostics panel for offline-first applications.
|
|
5
|
+
* Shows network status, service worker state, cache management, and queue stats.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Network status monitoring
|
|
9
|
+
* - Service worker status display
|
|
10
|
+
* - Cache management UI
|
|
11
|
+
* - Queue statistics display
|
|
12
|
+
* - Conflict resolution UI
|
|
13
|
+
* - Composable panels
|
|
14
|
+
*/
|
|
15
|
+
import { type ReactNode } from 'react';
|
|
16
|
+
export interface ServiceWorkerState {
|
|
17
|
+
isSupported: boolean;
|
|
18
|
+
registration: 'none' | 'installing' | 'waiting' | 'active';
|
|
19
|
+
updateAvailable: boolean;
|
|
20
|
+
controller: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface CacheInfo {
|
|
23
|
+
name: string;
|
|
24
|
+
itemCount: number;
|
|
25
|
+
sampleUrls: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface QueueStats {
|
|
28
|
+
pending: number;
|
|
29
|
+
syncing: number;
|
|
30
|
+
synced: number;
|
|
31
|
+
failed: number;
|
|
32
|
+
totalBytes: number;
|
|
33
|
+
}
|
|
34
|
+
export interface OfflineDiagnosticsProps {
|
|
35
|
+
/** Show network status panel */
|
|
36
|
+
showNetworkStatus?: boolean;
|
|
37
|
+
/** Show service worker panel */
|
|
38
|
+
showServiceWorker?: boolean;
|
|
39
|
+
/** Show cache management panel */
|
|
40
|
+
showCacheManagement?: boolean;
|
|
41
|
+
/** Show queue statistics panel */
|
|
42
|
+
showQueueStats?: boolean;
|
|
43
|
+
/** Show conflict resolution panel */
|
|
44
|
+
showConflicts?: boolean;
|
|
45
|
+
/** Callback when cache is cleared */
|
|
46
|
+
onClearCache?: (cacheName?: string) => Promise<void>;
|
|
47
|
+
/** CSS class for container */
|
|
48
|
+
className?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Network Status Panel
|
|
52
|
+
*/
|
|
53
|
+
export declare function NetworkStatusPanel(): ReactNode;
|
|
54
|
+
/**
|
|
55
|
+
* Service Worker Panel
|
|
56
|
+
*/
|
|
57
|
+
export declare function ServiceWorkerPanel(): ReactNode;
|
|
58
|
+
/**
|
|
59
|
+
* Cache Management Panel
|
|
60
|
+
*/
|
|
61
|
+
export declare function CacheManagementPanel({ onClearCache, }: {
|
|
62
|
+
onClearCache?: (cacheName?: string) => Promise<void>;
|
|
63
|
+
}): ReactNode;
|
|
64
|
+
/**
|
|
65
|
+
* Queue Stats Panel
|
|
66
|
+
*/
|
|
67
|
+
export declare function QueueStatsPanel({ stats, }: {
|
|
68
|
+
stats?: QueueStats;
|
|
69
|
+
}): ReactNode;
|
|
70
|
+
/**
|
|
71
|
+
* Conflicts Panel
|
|
72
|
+
*/
|
|
73
|
+
export declare function ConflictsPanel(): ReactNode;
|
|
74
|
+
/**
|
|
75
|
+
* Comprehensive offline diagnostics panel
|
|
76
|
+
*/
|
|
77
|
+
export declare function OfflineDiagnostics({ showNetworkStatus, showServiceWorker, showCacheManagement, showQueueStats, showConflicts, onClearCache, className, }: OfflineDiagnosticsProps): ReactNode;
|
|
78
|
+
export default OfflineDiagnostics;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PushNotifications Component
|
|
3
|
+
*
|
|
4
|
+
* Push notification management component for PWA applications.
|
|
5
|
+
* Handles subscription, permission, and notification sending.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - VAPID-based push subscription
|
|
9
|
+
* - Permission handling
|
|
10
|
+
* - Subscription serialization
|
|
11
|
+
* - Customizable UI via render props
|
|
12
|
+
* - Headless hook export
|
|
13
|
+
*/
|
|
14
|
+
import { type ReactNode } from 'react';
|
|
15
|
+
export interface PushSubscriptionData {
|
|
16
|
+
endpoint: string;
|
|
17
|
+
keys: {
|
|
18
|
+
p256dh: string;
|
|
19
|
+
auth: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface PushNotificationState {
|
|
23
|
+
/** Whether push is supported */
|
|
24
|
+
isSupported: boolean;
|
|
25
|
+
/** Current permission state */
|
|
26
|
+
permission: NotificationPermission | 'unsupported';
|
|
27
|
+
/** Current subscription (if subscribed) */
|
|
28
|
+
subscription: PushSubscriptionData | null;
|
|
29
|
+
/** Whether currently loading */
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
/** Last error message */
|
|
32
|
+
error: string | null;
|
|
33
|
+
/** Subscribe to push notifications */
|
|
34
|
+
subscribe: () => Promise<PushSubscriptionData | null>;
|
|
35
|
+
/** Unsubscribe from push notifications */
|
|
36
|
+
unsubscribe: () => Promise<boolean>;
|
|
37
|
+
/** Request permission */
|
|
38
|
+
requestPermission: () => Promise<NotificationPermission>;
|
|
39
|
+
/** Clear error */
|
|
40
|
+
clearError: () => void;
|
|
41
|
+
}
|
|
42
|
+
export interface PushNotificationsProps {
|
|
43
|
+
/** VAPID public key */
|
|
44
|
+
vapidPublicKey?: string;
|
|
45
|
+
/** Called when subscription changes */
|
|
46
|
+
onSubscribe?: (subscription: PushSubscriptionData) => Promise<void> | void;
|
|
47
|
+
/** Called when unsubscribing */
|
|
48
|
+
onUnsubscribe?: (endpoint: string) => Promise<void> | void;
|
|
49
|
+
/** Custom render function */
|
|
50
|
+
render?: (state: PushNotificationState) => ReactNode;
|
|
51
|
+
/** Show default UI */
|
|
52
|
+
showUI?: boolean;
|
|
53
|
+
/** CSS class for container */
|
|
54
|
+
className?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface UsePushNotificationsConfig {
|
|
57
|
+
/** VAPID public key */
|
|
58
|
+
vapidPublicKey?: string;
|
|
59
|
+
/** Service worker URL */
|
|
60
|
+
serviceWorkerUrl?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Hook for managing push notifications
|
|
64
|
+
*/
|
|
65
|
+
export declare function usePushNotifications(config?: UsePushNotificationsConfig): PushNotificationState;
|
|
66
|
+
/**
|
|
67
|
+
* Push notifications management component
|
|
68
|
+
*/
|
|
69
|
+
export declare function PushNotifications({ vapidPublicKey, onSubscribe, onUnsubscribe, render, showUI, className, }: PushNotificationsProps): ReactNode;
|
|
70
|
+
export default PushNotifications;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aeon Navigation Hooks
|
|
3
|
+
*
|
|
4
|
+
* React hooks for the cutting-edge navigation system.
|
|
5
|
+
* The navigation state itself is an Aeon - the site is a session.
|
|
6
|
+
*
|
|
7
|
+
* Recursive Aeon Architecture:
|
|
8
|
+
* - Component = Aeon entity
|
|
9
|
+
* - Page = Aeon session
|
|
10
|
+
* - Site = Aeon of sessions (routes are collaborative)
|
|
11
|
+
* - Federation = Aeon of Aeons (cross-site sync)
|
|
12
|
+
*/
|
|
13
|
+
import type { AeonNavigationEngine, NavigationOptions, PrefetchOptions, NavigationState, RoutePresenceInfo } from '@affectively/aeon-pages-runtime';
|
|
14
|
+
export interface NavigationPrediction {
|
|
15
|
+
route: string;
|
|
16
|
+
probability: number;
|
|
17
|
+
reason: 'history' | 'hover' | 'visibility' | 'community';
|
|
18
|
+
}
|
|
19
|
+
export interface AeonNavigationContextValue {
|
|
20
|
+
navigator: AeonNavigationEngine;
|
|
21
|
+
}
|
|
22
|
+
export declare const AeonNavigationContext: import("react").Context<AeonNavigationContextValue | null>;
|
|
23
|
+
/**
|
|
24
|
+
* Main navigation hook - provides navigation, prefetch, and state
|
|
25
|
+
*/
|
|
26
|
+
export declare function useAeonNavigation(): {
|
|
27
|
+
current: string;
|
|
28
|
+
previous: string | null;
|
|
29
|
+
history: string[];
|
|
30
|
+
isNavigating: boolean;
|
|
31
|
+
navigate: (href: string, options?: NavigationOptions) => Promise<void>;
|
|
32
|
+
prefetch: (href: string, options?: PrefetchOptions) => Promise<void>;
|
|
33
|
+
back: () => Promise<void>;
|
|
34
|
+
preloadAll: (onProgress?: (loaded: number, total: number) => void) => Promise<void>;
|
|
35
|
+
isPreloaded: (href: string) => boolean;
|
|
36
|
+
getCacheStats: () => import("@affectively/aeon-pages-runtime").CacheStats;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Route Presence hook - subscribe to who's viewing/editing routes
|
|
40
|
+
*
|
|
41
|
+
* Presence flows upward through the Aeon hierarchy:
|
|
42
|
+
* - Page presence = users on this page
|
|
43
|
+
* - Site presence = aggregate of all page presence
|
|
44
|
+
* - Federation presence = aggregate across sites
|
|
45
|
+
*
|
|
46
|
+
* Note: This is different from usePresence in provider.tsx which is for
|
|
47
|
+
* page-level editing presence. This hook is for navigation-level presence
|
|
48
|
+
* (who's viewing what routes before you navigate there).
|
|
49
|
+
*/
|
|
50
|
+
export declare function useRoutePresence(): {
|
|
51
|
+
getPresence: (route: string) => RoutePresenceInfo | null;
|
|
52
|
+
subscribePresence: (callback: (route: string, presence: RoutePresenceInfo) => void) => (() => void);
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Navigation prediction hook
|
|
56
|
+
*/
|
|
57
|
+
export declare function useNavigationPrediction(): {
|
|
58
|
+
predict: (fromRoute?: string) => NavigationPrediction[];
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Hook for observing links and auto-prefetching
|
|
62
|
+
*/
|
|
63
|
+
export declare function useLinkObserver(containerRef: React.RefObject<Element>): {
|
|
64
|
+
observe: () => () => void;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Hook for total preload progress
|
|
68
|
+
*/
|
|
69
|
+
export declare function useTotalPreload(): {
|
|
70
|
+
startPreload: (onProgress?: (loaded: number, total: number) => void) => Promise<void>;
|
|
71
|
+
getStats: () => import("@affectively/aeon-pages-runtime").CacheStats;
|
|
72
|
+
};
|
|
73
|
+
export type { NavigationOptions, PrefetchOptions, NavigationState, RoutePresenceInfo };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useConflicts Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for managing conflicts in offline-first applications.
|
|
5
|
+
* Provides access to conflict list, resolution methods, and statistics.
|
|
6
|
+
*/
|
|
7
|
+
export type ResolutionStrategy = 'local-wins' | 'remote-wins' | 'merge' | 'last-modified' | 'manual';
|
|
8
|
+
export interface Conflict {
|
|
9
|
+
id: string;
|
|
10
|
+
operationId: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
localData: Record<string, unknown>;
|
|
13
|
+
remoteData: Record<string, unknown>;
|
|
14
|
+
type: 'update_update' | 'delete_update' | 'update_delete' | 'concurrent';
|
|
15
|
+
severity: 'low' | 'medium' | 'high';
|
|
16
|
+
detectedAt: number;
|
|
17
|
+
resolution?: {
|
|
18
|
+
strategy: ResolutionStrategy;
|
|
19
|
+
resolvedData: Record<string, unknown>;
|
|
20
|
+
resolvedAt: number;
|
|
21
|
+
resolvedBy?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface ConflictStats {
|
|
25
|
+
total: number;
|
|
26
|
+
unresolved: number;
|
|
27
|
+
highSeverity: number;
|
|
28
|
+
byType: Record<Conflict['type'], number>;
|
|
29
|
+
byStrategy: Record<ResolutionStrategy, number>;
|
|
30
|
+
}
|
|
31
|
+
export interface UseConflictsResult {
|
|
32
|
+
/** All conflicts */
|
|
33
|
+
conflicts: Conflict[];
|
|
34
|
+
/** Unresolved conflicts only */
|
|
35
|
+
unresolvedConflicts: Conflict[];
|
|
36
|
+
/** High severity conflicts */
|
|
37
|
+
highSeverityConflicts: Conflict[];
|
|
38
|
+
/** Conflict statistics */
|
|
39
|
+
stats: ConflictStats;
|
|
40
|
+
/** Resolve a conflict */
|
|
41
|
+
resolveConflict: (conflictId: string, strategy: ResolutionStrategy, customData?: Record<string, unknown>) => Promise<void>;
|
|
42
|
+
/** Dismiss a conflict (remove without resolution) */
|
|
43
|
+
dismissConflict: (conflictId: string) => void;
|
|
44
|
+
/** Clear all resolved conflicts */
|
|
45
|
+
clearResolved: () => void;
|
|
46
|
+
/** Refresh conflicts from source */
|
|
47
|
+
refresh: () => void;
|
|
48
|
+
/** Whether conflicts are loading */
|
|
49
|
+
isLoading: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Hook to manage conflicts in offline-first applications
|
|
53
|
+
*/
|
|
54
|
+
export declare function useConflicts(sessionId?: string): UseConflictsResult;
|
|
55
|
+
/**
|
|
56
|
+
* Add a conflict to the store (for testing or external integration)
|
|
57
|
+
*/
|
|
58
|
+
export declare function addConflict(conflict: Conflict): void;
|
|
59
|
+
/**
|
|
60
|
+
* Get all conflicts from the store
|
|
61
|
+
*/
|
|
62
|
+
export declare function getAllConflicts(): Conflict[];
|
|
63
|
+
/**
|
|
64
|
+
* Clear all conflicts
|
|
65
|
+
*/
|
|
66
|
+
export declare function clearAllConflicts(): void;
|
|
67
|
+
export default useConflicts;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useNetworkState Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for monitoring network state and bandwidth.
|
|
5
|
+
* Provides real-time updates on connection quality and effective type.
|
|
6
|
+
*/
|
|
7
|
+
export type NetworkState = 'online' | 'offline' | 'poor' | 'unknown';
|
|
8
|
+
export interface BandwidthProfile {
|
|
9
|
+
/** Estimated bandwidth in Kbps */
|
|
10
|
+
speedKbps: number;
|
|
11
|
+
/** Estimated latency in ms */
|
|
12
|
+
latencyMs: number;
|
|
13
|
+
/** Reliability score (0-1) */
|
|
14
|
+
reliability: number;
|
|
15
|
+
/** Effective connection type */
|
|
16
|
+
effectiveType: '2g' | '3g' | '4g' | 'slow-2g' | 'unknown';
|
|
17
|
+
}
|
|
18
|
+
export interface NetworkStateResult {
|
|
19
|
+
/** Current network state */
|
|
20
|
+
state: NetworkState;
|
|
21
|
+
/** Whether currently online */
|
|
22
|
+
isOnline: boolean;
|
|
23
|
+
/** Whether on poor connection */
|
|
24
|
+
isPoor: boolean;
|
|
25
|
+
/** Bandwidth profile */
|
|
26
|
+
bandwidth: BandwidthProfile;
|
|
27
|
+
/** Time since last state change */
|
|
28
|
+
timeSinceChange: number;
|
|
29
|
+
/** Force refresh network state */
|
|
30
|
+
refresh: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Hook to monitor network state and bandwidth
|
|
34
|
+
*/
|
|
35
|
+
export declare function useNetworkState(): NetworkStateResult;
|
|
36
|
+
export default useNetworkState;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pilot Navigation Hook
|
|
3
|
+
*
|
|
4
|
+
* AI-driven navigation with user consent.
|
|
5
|
+
* Cyrano acts as the "pilot" - suggesting navigation destinations,
|
|
6
|
+
* but always with user consent before actually navigating.
|
|
7
|
+
*
|
|
8
|
+
* The pilot metaphor:
|
|
9
|
+
* - User is the captain
|
|
10
|
+
* - AI (Cyrano) is the pilot suggesting routes
|
|
11
|
+
* - Navigation only happens with captain's approval
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Pending navigation queue
|
|
15
|
+
* - Consent confirmation UI
|
|
16
|
+
* - History API integration (smooth client-side navigation)
|
|
17
|
+
* - Navigation analytics/tracking
|
|
18
|
+
*/
|
|
19
|
+
import { type NavigationOptions } from './useAeonNavigation';
|
|
20
|
+
export interface PilotNavigationIntent {
|
|
21
|
+
id: string;
|
|
22
|
+
destination: string;
|
|
23
|
+
reason?: string;
|
|
24
|
+
source: 'cyrano' | 'esi' | 'user' | 'system';
|
|
25
|
+
confidence?: number;
|
|
26
|
+
timestamp: number;
|
|
27
|
+
metadata?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
export interface PilotNavigationOptions extends NavigationOptions {
|
|
30
|
+
/** Whether to require explicit consent (default: true for AI sources) */
|
|
31
|
+
requireConsent?: boolean;
|
|
32
|
+
/** Reason for navigation (shown to user) */
|
|
33
|
+
reason?: string;
|
|
34
|
+
/** Source of navigation intent */
|
|
35
|
+
source?: PilotNavigationIntent['source'];
|
|
36
|
+
/** Confidence level (0-1) for AI-driven navigation */
|
|
37
|
+
confidence?: number;
|
|
38
|
+
/** Additional metadata */
|
|
39
|
+
metadata?: Record<string, unknown>;
|
|
40
|
+
/** Auto-navigate after delay (ms) if consent not required */
|
|
41
|
+
autoNavigateDelay?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface PilotNavigationState {
|
|
44
|
+
/** Current pending navigation intent awaiting consent */
|
|
45
|
+
pendingIntent: PilotNavigationIntent | null;
|
|
46
|
+
/** History of navigation intents */
|
|
47
|
+
intentHistory: PilotNavigationIntent[];
|
|
48
|
+
/** Whether navigation is in progress */
|
|
49
|
+
isNavigating: boolean;
|
|
50
|
+
}
|
|
51
|
+
type NavigationConsentCallback = (intent: PilotNavigationIntent) => Promise<boolean> | boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Hook for AI-piloted navigation with user consent
|
|
54
|
+
*/
|
|
55
|
+
export declare function usePilotNavigation(options?: {
|
|
56
|
+
/** Custom consent handler (if not provided, uses built-in pending state) */
|
|
57
|
+
onConsentRequired?: NavigationConsentCallback;
|
|
58
|
+
/** Maximum intent history to keep */
|
|
59
|
+
maxHistory?: number;
|
|
60
|
+
}): {
|
|
61
|
+
pendingIntent: PilotNavigationIntent | null;
|
|
62
|
+
intentHistory: PilotNavigationIntent[];
|
|
63
|
+
isNavigating: boolean;
|
|
64
|
+
current: string;
|
|
65
|
+
pilot: (destination: string, pilotOptions?: PilotNavigationOptions) => Promise<boolean>;
|
|
66
|
+
approve: () => Promise<boolean>;
|
|
67
|
+
reject: () => void;
|
|
68
|
+
clearPending: () => void;
|
|
69
|
+
navigateDirect: (destination: string, navOptions?: NavigationOptions) => Promise<void>;
|
|
70
|
+
prefetch: (href: string, options?: import("@affectively/aeon-pages-runtime").PrefetchOptions) => Promise<void>;
|
|
71
|
+
back: () => Promise<void>;
|
|
72
|
+
isPreloaded: (href: string) => boolean;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Parse navigation tags from AI response
|
|
76
|
+
* Returns array of destinations extracted from [navigate:/path] tags
|
|
77
|
+
*/
|
|
78
|
+
export declare function parseNavigationTags(text: string): {
|
|
79
|
+
destination: string;
|
|
80
|
+
fullMatch: string;
|
|
81
|
+
}[];
|
|
82
|
+
/**
|
|
83
|
+
* Remove navigation tags from text for display
|
|
84
|
+
*/
|
|
85
|
+
export declare function stripNavigationTags(text: string): string;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service Worker Hooks - Client communication with Aeon SW
|
|
3
|
+
*
|
|
4
|
+
* Provides React hooks for:
|
|
5
|
+
* - Total preload progress tracking
|
|
6
|
+
* - Cache status monitoring
|
|
7
|
+
* - Manual preload triggers
|
|
8
|
+
*/
|
|
9
|
+
export interface PreloadProgress {
|
|
10
|
+
loaded: number;
|
|
11
|
+
total: number;
|
|
12
|
+
percentage: number;
|
|
13
|
+
isComplete: boolean;
|
|
14
|
+
cachedRoutes: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface CacheStatus {
|
|
17
|
+
cached: number;
|
|
18
|
+
total: number;
|
|
19
|
+
routes: string[];
|
|
20
|
+
isReady: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Hook to register and track the Aeon service worker
|
|
24
|
+
*/
|
|
25
|
+
export declare function useAeonServiceWorker(): {
|
|
26
|
+
isRegistered: boolean;
|
|
27
|
+
isActive: boolean;
|
|
28
|
+
error: Error | null;
|
|
29
|
+
update: () => Promise<void>;
|
|
30
|
+
unregister: () => Promise<void>;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Hook to track total preload progress
|
|
34
|
+
*/
|
|
35
|
+
export declare function usePreloadProgress(): PreloadProgress;
|
|
36
|
+
/**
|
|
37
|
+
* Hook to get current cache status
|
|
38
|
+
*/
|
|
39
|
+
export declare function useCacheStatus(): CacheStatus & {
|
|
40
|
+
refresh: () => void;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Hook to trigger manual preload
|
|
44
|
+
*/
|
|
45
|
+
export declare function useManualPreload(): {
|
|
46
|
+
triggerPreload: () => void;
|
|
47
|
+
isPreloading: boolean;
|
|
48
|
+
progress: PreloadProgress;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Hook to prefetch a specific route
|
|
52
|
+
*/
|
|
53
|
+
export declare function usePrefetchRoute(): (route: string) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Hook to clear the cache
|
|
56
|
+
*/
|
|
57
|
+
export declare function useClearCache(): {
|
|
58
|
+
clearCache: () => Promise<void>;
|
|
59
|
+
isClearing: boolean;
|
|
60
|
+
};
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Additional React hooks for Aeon Pages
|
|
3
|
+
*/
|
|
4
|
+
import { type PresenceUser } from './provider';
|
|
5
|
+
/**
|
|
6
|
+
* useAeonVersion - Access version and migration tools
|
|
7
|
+
*/
|
|
8
|
+
export declare function useAeonVersion(): {
|
|
9
|
+
migrate: (toVersion: string) => Promise<void>;
|
|
10
|
+
current: string;
|
|
11
|
+
latest: string;
|
|
12
|
+
needsMigration: boolean;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* useAeonTree - Access the component tree for advanced manipulation
|
|
16
|
+
*/
|
|
17
|
+
export declare function useAeonTree(): {
|
|
18
|
+
tree: unknown;
|
|
19
|
+
updateTree: (path: string, value: unknown) => void;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* useCursorTracking - Automatically track cursor movement
|
|
23
|
+
*/
|
|
24
|
+
export declare function useCursorTracking(enabled?: boolean): void;
|
|
25
|
+
/**
|
|
26
|
+
* useEditableElement - Make an element collaboratively editable
|
|
27
|
+
*/
|
|
28
|
+
export declare function useEditableElement(elementPath: string): {
|
|
29
|
+
isFocused: boolean;
|
|
30
|
+
isBeingEditedByOther: boolean;
|
|
31
|
+
onFocus: () => void;
|
|
32
|
+
onBlur: () => void;
|
|
33
|
+
onChange: (value: unknown) => void;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* useOtherCursors - Get cursors of other users (excluding self)
|
|
37
|
+
*/
|
|
38
|
+
export declare function useOtherCursors(): PresenceUser[];
|
|
39
|
+
/**
|
|
40
|
+
* useOfflineStatus - Track offline status and pending operations
|
|
41
|
+
*/
|
|
42
|
+
export declare function useOfflineStatus(): {
|
|
43
|
+
isOffline: boolean;
|
|
44
|
+
isSyncing: boolean;
|
|
45
|
+
pendingOperations: number;
|
|
46
|
+
lastSyncAt: string | undefined;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* useCollaborativeInput - Hook for collaborative text input
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* function EditableTitle() {
|
|
54
|
+
* const { value, onChange, onFocus, onBlur, isEditing, editingBy } = useCollaborativeInput('title');
|
|
55
|
+
*
|
|
56
|
+
* return (
|
|
57
|
+
* <input
|
|
58
|
+
* value={value}
|
|
59
|
+
* onChange={(e) => onChange(e.target.value)}
|
|
60
|
+
* onFocus={onFocus}
|
|
61
|
+
* onBlur={onBlur}
|
|
62
|
+
* style={{ borderColor: editingBy ? 'blue' : undefined }}
|
|
63
|
+
* />
|
|
64
|
+
* );
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function useCollaborativeInput(key: string): {
|
|
69
|
+
value: string;
|
|
70
|
+
onChange: (newValue: string) => void;
|
|
71
|
+
onFocus: () => void;
|
|
72
|
+
onBlur: () => void;
|
|
73
|
+
isEditing: boolean;
|
|
74
|
+
editingBy: PresenceUser | undefined;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* useAeonEffect - Run effect when Aeon data changes
|
|
78
|
+
*/
|
|
79
|
+
export declare function useAeonEffect(key: string, effect: (value: unknown) => void | (() => void)): void;
|
|
80
|
+
/**
|
|
81
|
+
* useSessionId - Get the current session ID
|
|
82
|
+
*/
|
|
83
|
+
export declare function useSessionId(): string;
|
|
84
|
+
/**
|
|
85
|
+
* useRoute - Get the current route
|
|
86
|
+
*/
|
|
87
|
+
export declare function useRoute(): string;
|