@xnetjs/react 0.0.2 → 0.1.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.
@@ -0,0 +1,1584 @@
1
+ import { PropertyBuilder, DefinedSchema, QueryAST, QueryASTPlannerGate, QueryASTAggregateExecution, InferCreateProps, TaskSchema, NodeState, NodeId, AuthGrant } from '@xnetjs/data';
2
+ import { Q as QueryFilter, c as QueryListResult, F as FlatNode } from './useQuery-D7ajycrc.js';
3
+ import { TimelineEntry, HistoryTarget, HistoricalState, PropertyDiff, UndoManagerOptions, AuditEntry, ActivitySummary, DiffResult, BlameInfo, VerificationOptions, VerificationResult } from '@xnetjs/history';
4
+ import { DID, AuthAction, AuthTrace, AuthTraceStep } from '@xnetjs/core';
5
+ import { SyncStatus, SyncManager, SyncProgress } from '@xnetjs/runtime';
6
+ import * as react_jsx_runtime from 'react/jsx-runtime';
7
+ import { Identity, KeyBundle, PQKeyRegistry, HybridKeyBundle } from '@xnetjs/identity';
8
+ import * as react from 'react';
9
+ import { ReactNode, JSX as JSX$1 } from 'react';
10
+ import { SecurityLevel, UnifiedSignature, VerificationResult as VerificationResult$1 } from '@xnetjs/crypto';
11
+ import { PluginRegistry, RegisteredPlugin, ViewContribution, CommandContribution, SlashCommandContribution, SidebarContribution, EditorContribution, PropertyHandlerContribution, BlockContribution, SettingContribution, ImporterContribution } from '@xnetjs/plugins';
12
+ import './instrumentation-CpIuG2y5.js';
13
+ import './telemetry-context-B7r6H1KW.js';
14
+
15
+ interface TaskProjectionReferenceInput {
16
+ url: string;
17
+ provider: string | null;
18
+ kind: string | null;
19
+ refId: string | null;
20
+ title: string | null;
21
+ subtitle: string | null;
22
+ icon: string | null;
23
+ embedUrl: string | null;
24
+ metadata: string;
25
+ }
26
+ interface TaskProjectionInput {
27
+ taskId: string;
28
+ /** Surface-specific anchor (page block id or canvas object id) */
29
+ blockId: string;
30
+ title: string;
31
+ completed: boolean;
32
+ parentTaskId: string | null;
33
+ sortKey: string;
34
+ assignees: string[];
35
+ dueDate: string | null;
36
+ references: TaskProjectionReferenceInput[];
37
+ }
38
+ type TaskProjectionHost = 'page' | 'canvas';
39
+ interface UseTaskProjectionSyncOptions {
40
+ /** Which Task relation property anchors tasks to this surface */
41
+ host: TaskProjectionHost;
42
+ /** The hosting node id (page id or canvas id); null disables sync */
43
+ hostId: string | null;
44
+ debounceMs?: number;
45
+ }
46
+ interface UseTaskProjectionSyncResult {
47
+ handleTasksChange: (tasks: TaskProjectionInput[]) => void;
48
+ syncing: boolean;
49
+ error: Error | null;
50
+ }
51
+ declare function useTaskProjectionSync({ host, hostId, debounceMs }: UseTaskProjectionSyncOptions): UseTaskProjectionSyncResult;
52
+
53
+ /**
54
+ * usePageTaskSync - Reconcile page task rows with Task nodes.
55
+ *
56
+ * Checklist items inside page editors remain the inline editing surface, while
57
+ * Task nodes stay the canonical cross-surface records for querying and reuse.
58
+ * Thin wrapper over useTaskProjectionSync (host: 'page'); semantics in
59
+ * docs/specs/PAGE_TASK_RECONCILIATION.md.
60
+ */
61
+
62
+ type PageTaskReferenceInput = TaskProjectionReferenceInput;
63
+ type PageTaskInput = TaskProjectionInput;
64
+ interface UsePageTaskSyncOptions {
65
+ pageId: string | null;
66
+ debounceMs?: number;
67
+ }
68
+ type UsePageTaskSyncResult = UseTaskProjectionSyncResult;
69
+ declare function usePageTaskSync({ pageId, debounceMs }: UsePageTaskSyncOptions): UsePageTaskSyncResult;
70
+
71
+ /**
72
+ * useFind - guarded AST query hook for advanced Node reads.
73
+ */
74
+
75
+ type UseFindOptions<P extends Record<string, PropertyBuilder> = Record<string, PropertyBuilder>> = Pick<QueryFilter<P>, 'includeDeleted' | 'materializedView' | 'mode' | 'search' | 'source'>;
76
+ type UseFindResult<P extends Record<string, PropertyBuilder>> = QueryListResult<P> & {
77
+ /** Canonical planner gate for the supplied AST. */
78
+ plannerGate: QueryASTPlannerGate;
79
+ /** Runtime blockers that prevented this hook from executing the AST. */
80
+ blockers: string[];
81
+ /** Whether the AST was compiled and subscribed through the current query runtime. */
82
+ canExecute: boolean;
83
+ /** Aggregate results computed over the loaded query snapshot. */
84
+ aggregates: QueryASTAggregateExecution | null;
85
+ };
86
+ declare function useFind<P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>, ast: QueryAST, options?: UseFindOptions<P>): UseFindResult<P>;
87
+
88
+ /**
89
+ * useTasks - Task-specific query helpers built on top of useQuery.
90
+ */
91
+
92
+ type TaskNode = FlatNode<(typeof TaskSchema)['_properties']>;
93
+ type TaskStatus = NonNullable<InferCreateProps<(typeof TaskSchema)['_properties']>['status']>;
94
+ type UseTasksOptions = {
95
+ pageId?: string | null;
96
+ assigneeDid?: string | null;
97
+ includeCompleted?: boolean;
98
+ statuses?: TaskStatus[];
99
+ parentTaskId?: string | null;
100
+ dueDateFilter?: 'any' | 'overdue' | 'today' | 'next-7-days' | 'none';
101
+ };
102
+ type TaskTreeItem = {
103
+ task: TaskNode;
104
+ depth: number;
105
+ children: TaskTreeItem[];
106
+ };
107
+ type UseTasksResult = {
108
+ data: TaskNode[];
109
+ tree: TaskTreeItem[];
110
+ loading: boolean;
111
+ error: Error | null;
112
+ reload: () => void;
113
+ };
114
+ declare function useTasks({ pageId, assigneeDid, includeCompleted, statuses, parentTaskId, dueDateFilter }?: UseTasksOptions): UseTasksResult;
115
+
116
+ interface UseCommentsOptions {
117
+ /** The Node ID to get comments for (any schema) */
118
+ nodeId: string;
119
+ /** Optional: filter to specific anchor type */
120
+ anchorType?: 'text' | 'cell' | 'row' | 'column' | 'canvas-position' | 'canvas-object' | 'node';
121
+ }
122
+ interface CommentThread {
123
+ /** The root comment (holds anchor data and resolved state) */
124
+ root: CommentNode;
125
+ /** Replies to this thread (sorted by Lamport time) */
126
+ replies: CommentNode[];
127
+ }
128
+ /** Flattened comment node for easier access */
129
+ interface CommentNode {
130
+ id: string;
131
+ schemaId: string;
132
+ createdAt: number;
133
+ lamportTime: number;
134
+ wallTime: number;
135
+ properties: {
136
+ target: string;
137
+ targetSchema?: string;
138
+ inReplyTo?: string;
139
+ anchorType: string;
140
+ anchorData: string;
141
+ content: string;
142
+ attachments?: string[];
143
+ replyToUser?: string;
144
+ replyToCommentId?: string;
145
+ resolved: boolean;
146
+ resolvedBy?: string;
147
+ resolvedAt?: number;
148
+ edited: boolean;
149
+ editedAt?: number;
150
+ createdBy: string;
151
+ };
152
+ }
153
+ interface AddCommentOptions {
154
+ /** Comment content (GitHub-flavored markdown) */
155
+ content: string;
156
+ /** Type of anchor */
157
+ anchorType: 'text' | 'cell' | 'row' | 'column' | 'canvas-position' | 'canvas-object' | 'node';
158
+ /** JSON-encoded anchor data */
159
+ anchorData: string;
160
+ /** Schema IRI of the target Node (optimization) */
161
+ targetSchema?: string;
162
+ }
163
+ interface ReplyContext {
164
+ /** DID of user being replied to (for "replying to @user" UI) */
165
+ replyToUser?: string;
166
+ /** Comment ID being referenced (for "in reply to X" display) */
167
+ replyToCommentId?: string;
168
+ }
169
+ interface UseCommentsResult {
170
+ /** All comments on the target node */
171
+ comments: CommentNode[];
172
+ /** Comments grouped into threads (root + replies) */
173
+ threads: CommentThread[];
174
+ /** Total comment count */
175
+ count: number;
176
+ /** Count of unresolved threads */
177
+ unresolvedCount: number;
178
+ /** Whether loading */
179
+ loading: boolean;
180
+ /** Any error */
181
+ error: Error | null;
182
+ /** Add a new root comment */
183
+ addComment: (options: AddCommentOptions) => Promise<string | null>;
184
+ /** Reply to a thread */
185
+ replyTo: (rootCommentId: string, content: string, context?: ReplyContext) => Promise<string | null>;
186
+ /** Resolve a thread */
187
+ resolveThread: (rootCommentId: string) => Promise<void>;
188
+ /** Reopen a resolved thread */
189
+ reopenThread: (rootCommentId: string) => Promise<void>;
190
+ /** Delete a comment (soft delete) */
191
+ deleteComment: (commentId: string) => Promise<void>;
192
+ /** Delete an entire thread (root + all replies) */
193
+ deleteThread: (rootCommentId: string) => Promise<void>;
194
+ /** Edit a comment */
195
+ editComment: (commentId: string, content: string) => Promise<void>;
196
+ /** Reload comments */
197
+ reload: () => Promise<void>;
198
+ }
199
+ /**
200
+ * Universal hook for comments on any Node.
201
+ */
202
+ declare function useComments({ nodeId, anchorType }: UseCommentsOptions): UseCommentsResult;
203
+
204
+ /**
205
+ * Moderated comment hooks for public surfaces.
206
+ */
207
+
208
+ type CommentVisibility = 'visible' | 'collapsed' | 'quarantined' | 'hidden';
209
+ type PublicInteractionMode = 'open' | 'authenticated' | 'trusted' | 'reviewed' | 'closed';
210
+ type PublicInteractionSurface = 'comment' | 'reply' | 'reaction' | 'quote' | 'mention' | 'communityNote' | 'message' | 'crawl' | 'index';
211
+ type FirstContactMode = 'allow' | 'slow-mode' | 'quarantine' | 'review' | 'block';
212
+ type PublicModerationMode = 'off' | 'label-only' | 'post-review' | 'pre-filter' | 'pre-review';
213
+ interface ModerationLabelSummary {
214
+ id: string;
215
+ target: string;
216
+ value: string;
217
+ confidence: number;
218
+ sourceWeight: number;
219
+ sourceType?: string;
220
+ sourceDID?: string;
221
+ evidenceRefs?: string;
222
+ expiresAt?: number;
223
+ negates?: string;
224
+ createdAt: number;
225
+ }
226
+ interface PublicInteractionPolicySnapshot {
227
+ id: string;
228
+ target: string;
229
+ targetSchema?: string;
230
+ scope?: string;
231
+ commentMode: PublicInteractionMode;
232
+ replyMode: PublicInteractionMode;
233
+ reactionMode: PublicInteractionMode;
234
+ quoteMode: PublicInteractionMode;
235
+ mentionMode: PublicInteractionMode;
236
+ communityNoteMode: PublicInteractionMode;
237
+ messageMode: PublicInteractionMode;
238
+ crawlMode: PublicInteractionMode;
239
+ indexMode: PublicInteractionMode;
240
+ defaultVisibility: CommentVisibility;
241
+ firstContactMode: FirstContactMode;
242
+ moderationMode: PublicModerationMode;
243
+ slowModeSeconds?: number;
244
+ maxRootCommentsPerHour?: number;
245
+ maxRepliesPerHour?: number;
246
+ maxReactionsPerHour?: number;
247
+ maxMentionsPerComment?: number;
248
+ minimumAccountAgeHours?: number;
249
+ minimumReputation?: number;
250
+ trustThreshold?: number;
251
+ quarantineConfidenceThreshold?: number;
252
+ hideConfidenceThreshold?: number;
253
+ requiresVerifiedIdentity: boolean;
254
+ acceptsPolicySubscriptions: boolean;
255
+ policyLists: string[];
256
+ activeLabels: string[];
257
+ maintainers: string[];
258
+ moderators: string[];
259
+ policyPublishers: string[];
260
+ trustedDIDs: string[];
261
+ mutedDIDs: string[];
262
+ blockedDIDs: string[];
263
+ updatedAt: number;
264
+ createdAt: number;
265
+ }
266
+ interface ModeratedCommentNode {
267
+ comment: CommentNode;
268
+ visibility: CommentVisibility;
269
+ labels: ModerationLabelSummary[];
270
+ reasons: string[];
271
+ visible: boolean;
272
+ }
273
+ interface ModeratedCommentThread {
274
+ root: ModeratedCommentNode;
275
+ replies: ModeratedCommentNode[];
276
+ visibleReplies: ModeratedCommentNode[];
277
+ visible: boolean;
278
+ hiddenReplyCount: number;
279
+ collapsedReplyCount: number;
280
+ quarantinedReplyCount: number;
281
+ }
282
+ interface InteractionPermission {
283
+ allowed: boolean;
284
+ requiresReview: boolean;
285
+ mode: PublicInteractionMode;
286
+ reasons: string[];
287
+ }
288
+ interface ModerationFilterOptions {
289
+ hiddenLabels?: readonly string[];
290
+ collapsedLabels?: readonly string[];
291
+ includeCollapsed?: boolean;
292
+ includeQuarantined?: boolean;
293
+ includeHidden?: boolean;
294
+ minimumLabelConfidence?: number;
295
+ }
296
+ interface UseModeratedThreadOptions extends ModerationFilterOptions {
297
+ thread: CommentThread | null;
298
+ labelIndex?: ReadonlyMap<string, readonly ModerationLabelSummary[]>;
299
+ policy?: PublicInteractionPolicySnapshot | null;
300
+ }
301
+ interface UseVisibleCommentsOptions extends UseCommentsOptions, ModerationFilterOptions {
302
+ viewerDID?: string;
303
+ isAuthenticated?: boolean;
304
+ isVerified?: boolean;
305
+ policy?: PublicInteractionPolicySnapshot | null;
306
+ }
307
+ interface UseVisibleCommentsResult extends Omit<UseCommentsResult, 'comments' | 'threads' | 'count' | 'unresolvedCount' | 'addComment' | 'replyTo'> {
308
+ comments: CommentNode[];
309
+ threads: CommentThread[];
310
+ allComments: CommentNode[];
311
+ allThreads: CommentThread[];
312
+ moderatedThreads: ModeratedCommentThread[];
313
+ moderationByCommentId: ReadonlyMap<string, ModeratedCommentNode>;
314
+ moderationLabels: ModerationLabelSummary[];
315
+ policy: PublicInteractionPolicySnapshot | null;
316
+ policyLoading: boolean;
317
+ policyError: Error | null;
318
+ count: number;
319
+ unresolvedCount: number;
320
+ hiddenCount: number;
321
+ collapsedCount: number;
322
+ quarantinedCount: number;
323
+ canAddRootComment: InteractionPermission;
324
+ canReply: InteractionPermission;
325
+ addComment: (options: AddCommentOptions) => Promise<string | null>;
326
+ replyTo: (rootCommentId: string, content: string, context?: ReplyContext) => Promise<string | null>;
327
+ }
328
+ declare function summarizeModerationLabel(node: NodeState, now?: number): ModerationLabelSummary | null;
329
+ declare function summarizePublicInteractionPolicy(node: NodeState): PublicInteractionPolicySnapshot | null;
330
+ declare function selectActiveInteractionPolicy(policies: readonly PublicInteractionPolicySnapshot[]): PublicInteractionPolicySnapshot | null;
331
+ declare function selectPublicInteractionMode(policy: PublicInteractionPolicySnapshot | null, surface: PublicInteractionSurface): PublicInteractionMode;
332
+ declare function createModerationLabelIndex(labels: readonly ModerationLabelSummary[]): Map<string, ModerationLabelSummary[]>;
333
+ declare function evaluateInteractionPermission(mode: PublicInteractionMode, policy: PublicInteractionPolicySnapshot | null, options?: {
334
+ viewerDID?: string;
335
+ isAuthenticated?: boolean;
336
+ isVerified?: boolean;
337
+ }): InteractionPermission;
338
+ declare function evaluateCommentModeration(comment: CommentNode, options?: {
339
+ labels?: readonly ModerationLabelSummary[];
340
+ policy?: PublicInteractionPolicySnapshot | null;
341
+ } & ModerationFilterOptions): ModeratedCommentNode;
342
+ declare function moderateThread(thread: CommentThread, options?: {
343
+ labelIndex?: ReadonlyMap<string, readonly ModerationLabelSummary[]>;
344
+ policy?: PublicInteractionPolicySnapshot | null;
345
+ } & ModerationFilterOptions): ModeratedCommentThread;
346
+ declare function useModeratedThread({ thread, labelIndex, policy, hiddenLabels, collapsedLabels, includeCollapsed, includeQuarantined, includeHidden, minimumLabelConfidence }: UseModeratedThreadOptions): ModeratedCommentThread | null;
347
+ declare function useVisibleComments(options: UseVisibleCommentsOptions): UseVisibleCommentsResult;
348
+
349
+ /**
350
+ * Policy-filtered counters for public reactions and replies.
351
+ */
352
+
353
+ type ReactionType = 'like' | 'repost' | 'bookmark' | 'emoji';
354
+ interface ReactionNode {
355
+ id: string;
356
+ target: string;
357
+ targetSchema?: string;
358
+ reactionType: ReactionType;
359
+ reactor: string;
360
+ emoji?: string;
361
+ annotation?: string;
362
+ createdAt: number;
363
+ createdBy: string;
364
+ }
365
+ interface ReactionCounterSnapshot {
366
+ likes: number;
367
+ reposts: number;
368
+ bookmarks: number;
369
+ emoji: number;
370
+ replies: number;
371
+ totalReactions: number;
372
+ total: number;
373
+ }
374
+ interface UsePolicyFilteredReactionCountersOptions extends ModerationFilterOptions {
375
+ nodeId: string;
376
+ targetSchema?: string;
377
+ viewerDID?: string;
378
+ isAuthenticated?: boolean;
379
+ isVerified?: boolean;
380
+ policy?: PublicInteractionPolicySnapshot | null;
381
+ }
382
+ interface AddReactionOptions {
383
+ reactionType: ReactionType;
384
+ emoji?: string;
385
+ annotation?: string;
386
+ }
387
+ interface UsePolicyFilteredReactionCountersResult {
388
+ reactions: ReactionNode[];
389
+ visibleReactions: ReactionNode[];
390
+ counts: ReactionCounterSnapshot;
391
+ rawCounts: ReactionCounterSnapshot;
392
+ hiddenReactionCount: number;
393
+ loading: boolean;
394
+ error: Error | null;
395
+ policy: PublicInteractionPolicySnapshot | null;
396
+ canReact: InteractionPermission;
397
+ canRepost: InteractionPermission;
398
+ addReaction: (options: AddReactionOptions) => Promise<string | null>;
399
+ removeReaction: (reactionId: string) => Promise<void>;
400
+ toggleReaction: (options: AddReactionOptions) => Promise<string | null>;
401
+ reload: () => Promise<void>;
402
+ }
403
+ declare function summarizeReactionNode(node: NodeState): ReactionNode | null;
404
+ declare function isReactionVisible(reaction: ReactionNode, labels: readonly ModerationLabelSummary[], policy: PublicInteractionPolicySnapshot | null, options?: ModerationFilterOptions): boolean;
405
+ declare function dedupeReactions(reactions: readonly ReactionNode[]): ReactionNode[];
406
+ declare function createReactionCounterSnapshot(reactions: readonly ReactionNode[], replies: number): ReactionCounterSnapshot;
407
+ declare function usePolicyFilteredReactionCounters({ nodeId, targetSchema, viewerDID, isAuthenticated, isVerified, policy: providedPolicy, hiddenLabels, collapsedLabels, includeCollapsed, includeQuarantined, includeHidden, minimumLabelConfidence }: UsePolicyFilteredReactionCountersOptions): UsePolicyFilteredReactionCountersResult;
408
+
409
+ /**
410
+ * Message request and first-contact quarantine helpers.
411
+ */
412
+
413
+ type MessageRequestStatus = 'pending' | 'accepted' | 'declined' | 'quarantined' | 'blocked' | 'expired';
414
+ type FirstContactAdmission = 'allow' | 'message-request' | 'quarantine' | 'review' | 'block';
415
+ type FirstContactVisibility = 'inbox' | 'requests' | 'quarantine' | 'hidden';
416
+ type MessageRequestNode = {
417
+ id: string;
418
+ conversationKey: string;
419
+ sender: string;
420
+ recipient: string;
421
+ target?: string;
422
+ targetSchema?: string;
423
+ firstMessageRef?: string;
424
+ firstMessagePreview?: string;
425
+ status: MessageRequestStatus;
426
+ admission: FirstContactAdmission;
427
+ reasonCodes: string[];
428
+ confidence?: number;
429
+ policy?: string;
430
+ policyMode?: FirstContactMode;
431
+ quarantineUntil?: number;
432
+ expiresAt?: number;
433
+ respondedAt?: number;
434
+ respondedBy?: string;
435
+ reviewers: string[];
436
+ notes?: string;
437
+ createdAt: number;
438
+ createdBy: string;
439
+ };
440
+ type FirstContactDecisionInput = {
441
+ senderDID?: string;
442
+ recipientDID?: string;
443
+ policy?: PublicInteractionPolicySnapshot | null;
444
+ existingRequests?: readonly MessageRequestNode[];
445
+ isAuthenticated?: boolean;
446
+ isVerified?: boolean;
447
+ now?: number;
448
+ };
449
+ type FirstContactDecision = {
450
+ admission: FirstContactAdmission;
451
+ status: MessageRequestStatus;
452
+ visibility: FirstContactVisibility;
453
+ notifyRecipient: boolean;
454
+ requiresReview: boolean;
455
+ shouldCreateRequest: boolean;
456
+ reasons: string[];
457
+ reasonCodes: string[];
458
+ confidence: number;
459
+ quarantineUntil?: number;
460
+ };
461
+ type CreateMessageRequestOptions = {
462
+ senderDID: string;
463
+ recipientDID: string;
464
+ target?: string;
465
+ targetSchema?: string;
466
+ firstMessageRef?: string;
467
+ firstMessagePreview?: string;
468
+ expiresAt?: number;
469
+ reviewers?: readonly string[];
470
+ notes?: string;
471
+ };
472
+ type MessageRequestProperties = {
473
+ conversationKey: string;
474
+ sender: string;
475
+ recipient: string;
476
+ target?: string;
477
+ targetSchema?: string;
478
+ firstMessageRef?: string;
479
+ firstMessagePreview?: string;
480
+ status: MessageRequestStatus;
481
+ admission: FirstContactAdmission;
482
+ reasonCodes: string[];
483
+ confidence: number;
484
+ policy?: string;
485
+ policyMode?: FirstContactMode;
486
+ quarantineUntil?: number;
487
+ expiresAt?: number;
488
+ reviewers: string[];
489
+ notes?: string;
490
+ };
491
+ type UseMessageRequestsOptions = {
492
+ recipientDID?: string;
493
+ senderDID?: string;
494
+ policy?: PublicInteractionPolicySnapshot | null;
495
+ isAuthenticated?: boolean;
496
+ isVerified?: boolean;
497
+ includeResolved?: boolean;
498
+ };
499
+ type UseMessageRequestsResult = {
500
+ requests: MessageRequestNode[];
501
+ pendingRequests: MessageRequestNode[];
502
+ quarantinedRequests: MessageRequestNode[];
503
+ acceptedRequests: MessageRequestNode[];
504
+ blockedRequests: MessageRequestNode[];
505
+ loading: boolean;
506
+ error: Error | null;
507
+ evaluateFirstContact: (input: FirstContactDecisionInput) => FirstContactDecision;
508
+ createMessageRequest: (options: CreateMessageRequestOptions) => Promise<string | null>;
509
+ acceptRequest: (requestId: string, responderDID?: string) => Promise<void>;
510
+ declineRequest: (requestId: string, responderDID?: string) => Promise<void>;
511
+ quarantineRequest: (requestId: string, responderDID?: string) => Promise<void>;
512
+ blockRequest: (requestId: string, responderDID?: string) => Promise<void>;
513
+ reload: () => Promise<void>;
514
+ };
515
+ declare function createConversationKey(senderDID: string, recipientDID: string): string;
516
+ declare function summarizeMessageRequest(node: NodeState, now?: number): MessageRequestNode | null;
517
+ declare function findLatestMessageRequest(requests: readonly MessageRequestNode[], senderDID: string, recipientDID: string): MessageRequestNode | null;
518
+ declare function hasAcceptedContact(requests: readonly MessageRequestNode[], senderDID: string, recipientDID: string): boolean;
519
+ declare function evaluateFirstContactDecision({ senderDID, recipientDID, policy, existingRequests, isAuthenticated, isVerified, now }: FirstContactDecisionInput): FirstContactDecision;
520
+ declare function createMessageRequestProperties(options: CreateMessageRequestOptions, decision: FirstContactDecision, policy?: PublicInteractionPolicySnapshot | null): MessageRequestProperties;
521
+ declare function useMessageRequests({ recipientDID, senderDID, policy, isAuthenticated, isVerified, includeResolved }?: UseMessageRequestsOptions): UseMessageRequestsResult;
522
+
523
+ /**
524
+ * Get the unresolved comment count for a Node.
525
+ *
526
+ * @param nodeId - The Node ID to get comment count for
527
+ * @returns The number of unresolved comment threads
528
+ */
529
+ declare function useCommentCount(nodeId: string): number;
530
+ /**
531
+ * Get detailed comment counts for a Node.
532
+ *
533
+ * @param nodeId - The Node ID to get comment counts for
534
+ * @returns Object with total and unresolved counts
535
+ */
536
+ declare function useCommentCounts(nodeId: string): {
537
+ total: number;
538
+ unresolved: number;
539
+ resolved: number;
540
+ };
541
+
542
+ /**
543
+ * useHistory - React hook for node history / time travel
544
+ *
545
+ * Provides point-in-time reconstruction, timeline browsing,
546
+ * and state materialization for a node.
547
+ *
548
+ * @example
549
+ * ```tsx
550
+ * const { timeline, materializeAt, diff, changeCount, loading } = useHistory(nodeId)
551
+ *
552
+ * // Get timeline
553
+ * const entries = timeline
554
+ *
555
+ * // Materialize at a specific point
556
+ * const historical = await materializeAt({ type: 'index', index: 5 })
557
+ *
558
+ * // Diff two points
559
+ * const diffs = await diff({ type: 'index', index: 0 }, { type: 'latest' })
560
+ * ```
561
+ */
562
+
563
+ interface UseHistoryResult {
564
+ /** Full timeline of changes for the node */
565
+ timeline: TimelineEntry[];
566
+ /** Total number of changes */
567
+ changeCount: number;
568
+ /** Reconstruct node state at a target point */
569
+ materializeAt: (target: HistoryTarget) => Promise<HistoricalState | null>;
570
+ /** Diff between two points */
571
+ diff: (from: HistoryTarget, to: HistoryTarget) => Promise<PropertyDiff[]>;
572
+ /** Create a revert payload to restore to a historical point */
573
+ createRevertPayload: (target: HistoryTarget) => Promise<Record<string, unknown> | null>;
574
+ /** Whether the timeline is loading */
575
+ loading: boolean;
576
+ /** Any error */
577
+ error: Error | null;
578
+ /** Reload the timeline */
579
+ reload: () => Promise<void>;
580
+ }
581
+ declare function useHistory(nodeId: NodeId | null): UseHistoryResult;
582
+
583
+ /**
584
+ * useUndo - React hook for per-node undo/redo
585
+ *
586
+ * Wraps UndoManager to provide undo/redo actions, stack depth,
587
+ * and canUndo/canRedo state for a given node.
588
+ *
589
+ * @example
590
+ * ```tsx
591
+ * const { undo, redo, canUndo, canRedo, undoCount, redoCount } = useUndo(nodeId)
592
+ *
593
+ * // Wire to keyboard shortcuts
594
+ * <button onClick={undo} disabled={!canUndo}>Undo</button>
595
+ * <button onClick={redo} disabled={!canRedo}>Redo</button>
596
+ * ```
597
+ */
598
+
599
+ interface UseUndoOptions {
600
+ /** The local user's DID (required for undo to work) */
601
+ localDID: DID | null;
602
+ /** UndoManager configuration overrides */
603
+ options?: Partial<UndoManagerOptions>;
604
+ }
605
+ interface UseUndoResult {
606
+ /** Undo the last change for this node */
607
+ undo: () => Promise<boolean>;
608
+ /** Redo the last undone change for this node */
609
+ redo: () => Promise<boolean>;
610
+ /** Undo all changes in a batch */
611
+ undoBatch: (batchId: string) => Promise<boolean>;
612
+ /** Whether undo is available */
613
+ canUndo: boolean;
614
+ /** Whether redo is available */
615
+ canRedo: boolean;
616
+ /** Number of undo entries */
617
+ undoCount: number;
618
+ /** Number of redo entries */
619
+ redoCount: number;
620
+ /** Clear undo/redo stacks for this node */
621
+ clear: () => void;
622
+ }
623
+ declare function useUndo(nodeId: NodeId | null, opts: UseUndoOptions): UseUndoResult;
624
+
625
+ /**
626
+ * useAudit - React hook for querying the audit log
627
+ *
628
+ * Provides paginated, filterable access to change audit entries
629
+ * and activity summaries for nodes.
630
+ *
631
+ * @example
632
+ * ```tsx
633
+ * const { entries, activity, loading } = useAudit(nodeId)
634
+ * const { entries: filtered } = useAudit(nodeId, { operations: ['create', 'delete'] })
635
+ * ```
636
+ */
637
+
638
+ interface UseAuditOptions {
639
+ /** Filter by operations */
640
+ operations?: ('create' | 'update' | 'delete' | 'restore')[];
641
+ /** Filter by author DID */
642
+ author?: string;
643
+ /** Time range filter [from, to] in wall clock ms */
644
+ timeRange?: [number, number];
645
+ /** Max entries to return */
646
+ limit?: number;
647
+ /** Sort order */
648
+ order?: 'asc' | 'desc';
649
+ }
650
+ interface UseAuditResult {
651
+ /** Audit entries matching the query */
652
+ entries: AuditEntry[];
653
+ /** Activity summary for the node */
654
+ activity: ActivitySummary | null;
655
+ /** Whether loading */
656
+ loading: boolean;
657
+ /** Any error */
658
+ error: Error | null;
659
+ /** Reload audit data */
660
+ reload: () => Promise<void>;
661
+ }
662
+ declare function useAudit(nodeId: NodeId | null, options?: UseAuditOptions): UseAuditResult;
663
+
664
+ /**
665
+ * useDiff - React hook for comparing node state between two points
666
+ *
667
+ * Wraps DiffEngine to provide on-demand diffs between any two
668
+ * HistoryTarget points.
669
+ *
670
+ * @example
671
+ * ```tsx
672
+ * const { diff, result, loading } = useDiff(nodeId)
673
+ *
674
+ * // Compare creation to latest
675
+ * await diff({ type: 'index', index: 0 }, { type: 'latest' })
676
+ *
677
+ * // Show result
678
+ * result?.diffs.forEach(d => console.log(d.property, d.type))
679
+ * ```
680
+ */
681
+
682
+ interface UseDiffResult {
683
+ /** Compute diff between two points */
684
+ diff: (from: HistoryTarget, to: HistoryTarget) => Promise<void>;
685
+ /** Diff N changes back from current */
686
+ diffFromCurrent: (changesAgo: number) => Promise<void>;
687
+ /** Latest diff result */
688
+ result: DiffResult | null;
689
+ /** Whether diffing */
690
+ loading: boolean;
691
+ /** Any error */
692
+ error: Error | null;
693
+ }
694
+ declare function useDiff(nodeId: NodeId | null): UseDiffResult;
695
+
696
+ /**
697
+ * useBlame - React hook for per-property attribution
698
+ *
699
+ * Shows who last changed each property, how many times,
700
+ * and the full edit history.
701
+ *
702
+ * @example
703
+ * ```tsx
704
+ * const { blame, loading, reload } = useBlame(nodeId)
705
+ *
706
+ * blame.forEach(b => {
707
+ * console.log(`${b.property}: last changed by ${b.lastChangedBy}, ${b.totalEdits} edits`)
708
+ * })
709
+ * ```
710
+ */
711
+
712
+ interface UseBlameResult {
713
+ /** Blame info for all properties */
714
+ blame: BlameInfo[];
715
+ /** Whether loading */
716
+ loading: boolean;
717
+ /** Any error */
718
+ error: Error | null;
719
+ /** Reload blame data */
720
+ reload: () => Promise<void>;
721
+ }
722
+ declare function useBlame(nodeId: NodeId | null): UseBlameResult;
723
+
724
+ /**
725
+ * useVerification - React hook for cryptographic chain verification
726
+ *
727
+ * Runs verification on a node's change history and reports
728
+ * validity, errors, and statistics.
729
+ *
730
+ * @example
731
+ * ```tsx
732
+ * const { verify, result, loading } = useVerification(nodeId)
733
+ *
734
+ * await verify()
735
+ * if (result?.valid) {
736
+ * console.log('Chain is valid!', result.stats)
737
+ * } else {
738
+ * console.log('Errors:', result?.errors)
739
+ * }
740
+ * ```
741
+ */
742
+
743
+ interface UseVerificationResult {
744
+ /** Run full verification */
745
+ verify: (options?: VerificationOptions) => Promise<void>;
746
+ /** Run quick check (hash + chain only) */
747
+ quickCheck: () => Promise<{
748
+ valid: boolean;
749
+ errors: number;
750
+ } | null>;
751
+ /** Latest verification result */
752
+ result: VerificationResult | null;
753
+ /** Whether verification is running */
754
+ loading: boolean;
755
+ /** Verification progress (0-1) */
756
+ progress: number;
757
+ /** Any error */
758
+ error: Error | null;
759
+ }
760
+ declare function useVerification(nodeId: NodeId | null): UseVerificationResult;
761
+
762
+ /**
763
+ * useHubStatus - Access hub connection status from context.
764
+ */
765
+
766
+ declare function useHubStatus(): SyncStatus;
767
+
768
+ /**
769
+ * useCan - Check current user's permissions for a node.
770
+ */
771
+ interface UseCanResult {
772
+ canRead: boolean;
773
+ canWrite: boolean;
774
+ canDelete: boolean;
775
+ canShare: boolean;
776
+ loading: boolean;
777
+ error: Error | null;
778
+ isFresh: boolean;
779
+ evaluatedAt: number;
780
+ }
781
+ declare function useCan(nodeId: string): UseCanResult;
782
+
783
+ /**
784
+ * useCanEdit - Resolve editor/viewer capabilities for a node.
785
+ */
786
+ type UseCanEditResult = {
787
+ canEdit: boolean;
788
+ canView: boolean;
789
+ loading: boolean;
790
+ error: Error | null;
791
+ roles: string[];
792
+ };
793
+ declare function useCanEdit(nodeId: string): UseCanEditResult;
794
+
795
+ /**
796
+ * useGrants - Read and mutate grants for a node.
797
+ */
798
+
799
+ interface GrantInput {
800
+ to: DID;
801
+ actions: AuthAction[];
802
+ resource?: string;
803
+ expiresIn?: string | number;
804
+ parentGrantId?: string;
805
+ }
806
+ interface UseGrantsResult {
807
+ grants: AuthGrant[];
808
+ loading: boolean;
809
+ error: Error | null;
810
+ grant: (input: GrantInput) => Promise<AuthGrant>;
811
+ revoke: (grantId: string) => Promise<void>;
812
+ }
813
+ type GrantConsentSummary = {
814
+ grantee: DID;
815
+ resource: string;
816
+ actions: AuthAction[];
817
+ expiresAt: number;
818
+ what: string;
819
+ where: string;
820
+ howLong: string;
821
+ };
822
+ declare function describeGrantConsent(input: GrantInput, defaultResource: string, now?: number): GrantConsentSummary;
823
+ declare function useGrants(nodeId: string): UseGrantsResult;
824
+
825
+ /**
826
+ * useAuthTrace - Surface store.auth.explain traces for auth UX and debugging.
827
+ */
828
+
829
+ type AuthTraceSummary = {
830
+ allowed: boolean;
831
+ action: AuthAction;
832
+ resource: string;
833
+ roles: string[];
834
+ grants: string[];
835
+ reasons: string[];
836
+ evaluatedAt: number;
837
+ duration: number;
838
+ steps: AuthTraceStep[];
839
+ };
840
+ type UseAuthTraceResult = {
841
+ trace: AuthTrace | null;
842
+ summary: AuthTraceSummary | null;
843
+ loading: boolean;
844
+ error: Error | null;
845
+ refresh: () => Promise<void>;
846
+ };
847
+ type UseAuthTraceOptions = {
848
+ nodeId: string;
849
+ action: AuthAction;
850
+ enabled?: boolean;
851
+ };
852
+ declare function summarizeAuthTrace(trace: AuthTrace): AuthTraceSummary;
853
+ declare function useAuthTrace({ nodeId, action, enabled }: UseAuthTraceOptions): UseAuthTraceResult;
854
+
855
+ interface UseBackupReturn {
856
+ upload: (docId: string, plaintext: Uint8Array) => Promise<void>;
857
+ download: (docId: string) => Promise<Uint8Array | null>;
858
+ uploading: boolean;
859
+ }
860
+ declare function useBackup(): UseBackupReturn;
861
+
862
+ interface FileRef {
863
+ cid: string;
864
+ name: string;
865
+ mimeType: string;
866
+ size: number;
867
+ }
868
+ interface UseFileUploadReturn {
869
+ upload: (file: File) => Promise<FileRef>;
870
+ uploading: boolean;
871
+ progress: number;
872
+ }
873
+ declare function useFileUpload(): UseFileUploadReturn;
874
+
875
+ interface HubSearchOptions {
876
+ schemaIri?: string;
877
+ limit?: number;
878
+ offset?: number;
879
+ }
880
+ interface HubSearchResult {
881
+ docId: string;
882
+ title: string;
883
+ schemaIri: string;
884
+ snippet: string;
885
+ rank: number;
886
+ }
887
+ interface HubSearchState {
888
+ search: (query: string, options?: HubSearchOptions) => Promise<HubSearchResult[]>;
889
+ results: HubSearchResult[];
890
+ loading: boolean;
891
+ error: Error | null;
892
+ }
893
+ declare function useHubSearch(): HubSearchState;
894
+
895
+ /**
896
+ * useRemoteSchema - Hub schema registry fetch hook.
897
+ */
898
+ interface RemoteSchemaDefinition {
899
+ iri: string;
900
+ version: number;
901
+ name: string;
902
+ description: string;
903
+ definition: Record<string, unknown>;
904
+ authorDid: string;
905
+ propertiesCount: number;
906
+ createdAt: number;
907
+ }
908
+ interface RemoteSchemaState {
909
+ schema: RemoteSchemaDefinition | null;
910
+ loading: boolean;
911
+ error: Error | null;
912
+ }
913
+ declare const useRemoteSchema: (iri: string | undefined) => RemoteSchemaState;
914
+
915
+ /**
916
+ * usePeerDiscovery - hub peer discovery hook.
917
+ */
918
+ interface DiscoveredPeer {
919
+ did: string;
920
+ displayName?: string;
921
+ endpoints: Array<{
922
+ type: string;
923
+ address: string;
924
+ priority?: number;
925
+ }>;
926
+ lastSeen: number;
927
+ isOnline: boolean;
928
+ }
929
+ declare const usePeerDiscovery: () => {
930
+ peers: DiscoveredPeer[];
931
+ resolve: (did: string) => Promise<DiscoveredPeer | null>;
932
+ refresh: () => Promise<void>;
933
+ loading: boolean;
934
+ };
935
+
936
+ declare function HubStatusIndicator(): JSX.Element;
937
+
938
+ /**
939
+ * Skeleton loading placeholder.
940
+ *
941
+ * Shows a pulsing placeholder while content is loading. Supports
942
+ * different shapes (text lines, circles, rectangles).
943
+ */
944
+ type SkeletonProps = {
945
+ /** Width (CSS value). Default: '100%'. */
946
+ width?: string | number;
947
+ /** Height (CSS value). Default: '1em'. */
948
+ height?: string | number;
949
+ /** Border radius. Use '50%' for circles. Default: '4px'. */
950
+ borderRadius?: string | number;
951
+ /** Additional inline styles. */
952
+ style?: React.CSSProperties;
953
+ /** Number of lines to render. Default: 1. */
954
+ lines?: number;
955
+ /** Gap between lines. Default: '0.5rem'. */
956
+ gap?: string;
957
+ };
958
+ declare function Skeleton({ width, height, borderRadius, style, lines, gap }: SkeletonProps): JSX.Element;
959
+ /**
960
+ * Inject the skeleton keyframes into the document head.
961
+ * Call once at app startup, or include the CSS in your stylesheet:
962
+ *
963
+ * ```css
964
+ * @keyframes xnet-skeleton-pulse {
965
+ * 0% { background-position: 200% 0; }
966
+ * 100% { background-position: -200% 0; }
967
+ * }
968
+ * ```
969
+ */
970
+ declare function injectSkeletonStyles(): void;
971
+
972
+ interface DemoBannerProps {
973
+ /** How many hours until demo data expires */
974
+ evictionHours: number;
975
+ /** Called when banner is dismissed */
976
+ onDismiss?: () => void;
977
+ }
978
+ /**
979
+ * DemoBanner component
980
+ *
981
+ * @example
982
+ * ```tsx
983
+ * <DemoBanner evictionHours={24} />
984
+ * ```
985
+ */
986
+ declare function DemoBanner({ evictionHours, onDismiss }: DemoBannerProps): react_jsx_runtime.JSX.Element | null;
987
+
988
+ /**
989
+ * DemoQuotaIndicator - Shows storage quota usage for demo mode
990
+ *
991
+ * Displays a progress bar with bytes used / limit.
992
+ * Colors change at warning (80%) and critical (95%) thresholds.
993
+ */
994
+ interface DemoQuotaIndicatorProps {
995
+ /** Bytes currently used */
996
+ usedBytes: number;
997
+ /** Total quota limit in bytes */
998
+ limitBytes: number;
999
+ }
1000
+ /**
1001
+ * DemoQuotaIndicator component
1002
+ *
1003
+ * @example
1004
+ * ```tsx
1005
+ * <DemoQuotaIndicator usedBytes={5242880} limitBytes={10485760} />
1006
+ * ```
1007
+ */
1008
+ declare function DemoQuotaIndicator({ usedBytes, limitBytes }: DemoQuotaIndicatorProps): react_jsx_runtime.JSX.Element;
1009
+
1010
+ /**
1011
+ * DemoDataExpiredScreen - Full-screen message when demo data is evicted
1012
+ *
1013
+ * Shown when the user's demo data has been cleaned up after inactivity.
1014
+ * Provides options to start fresh or download the desktop app.
1015
+ */
1016
+ /**
1017
+ * DemoDataExpiredScreen component
1018
+ *
1019
+ * @example
1020
+ * ```tsx
1021
+ * if (dataExpired) {
1022
+ * return <DemoDataExpiredScreen />
1023
+ * }
1024
+ * ```
1025
+ */
1026
+ declare function DemoDataExpiredScreen(): react_jsx_runtime.JSX.Element;
1027
+
1028
+ /**
1029
+ * Demo mode limits (from hub handshake)
1030
+ */
1031
+ interface DemoLimits {
1032
+ /** Storage quota in bytes */
1033
+ quotaBytes: number;
1034
+ /** Maximum number of documents */
1035
+ maxDocs: number;
1036
+ /** Eviction time in hours */
1037
+ evictionHours: number;
1038
+ }
1039
+ /**
1040
+ * Demo mode usage stats (future: populated from hub)
1041
+ */
1042
+ interface DemoUsage {
1043
+ /** Bytes currently used */
1044
+ usedBytes: number;
1045
+ /** Number of documents */
1046
+ docCount: number;
1047
+ }
1048
+ /**
1049
+ * Demo mode state
1050
+ */
1051
+ interface DemoModeState {
1052
+ /** Whether connected to a demo hub */
1053
+ isDemo: boolean;
1054
+ /** Demo mode limits (if in demo mode) */
1055
+ limits?: DemoLimits;
1056
+ /** Current usage (if in demo mode and available) */
1057
+ usage?: DemoUsage;
1058
+ }
1059
+ /**
1060
+ * Hook to detect and track demo mode from hub connection
1061
+ *
1062
+ * Listens for the handshake message from the hub which includes `isDemo`
1063
+ * and `demoLimits` fields when connected to a demo hub.
1064
+ *
1065
+ * @example
1066
+ * ```tsx
1067
+ * function App() {
1068
+ * const { isDemo, limits } = useDemoMode()
1069
+ *
1070
+ * return (
1071
+ * <div>
1072
+ * {isDemo && limits && (
1073
+ * <DemoBanner evictionHours={limits.evictionHours} />
1074
+ * )}
1075
+ * <MainContent />
1076
+ * </div>
1077
+ * )
1078
+ * }
1079
+ * ```
1080
+ */
1081
+ declare function useDemoMode(): DemoModeState;
1082
+
1083
+ /**
1084
+ * useSyncManager - Access the Background Sync Manager from context
1085
+ *
1086
+ * Returns null if SyncManager is not available (disabled, not initialized,
1087
+ * or when running outside XNetProvider).
1088
+ */
1089
+
1090
+ declare function useSyncManager(): SyncManager | null;
1091
+
1092
+ /**
1093
+ * @xnetjs/react/onboarding - State machine for the onboarding flow
1094
+ *
1095
+ * States:
1096
+ * welcome → authenticating → connecting-hub → ready → complete
1097
+ * ↓ ↑
1098
+ * auth-error ──────── (retry) ────────┘
1099
+ * welcome → unsupported-browser (terminal)
1100
+ * welcome → import-identity → qr-scan/recovery-phrase → connecting-hub
1101
+ */
1102
+
1103
+ type OnboardingState = 'welcome' | 'authenticating' | 'auth-error' | 'unsupported-browser' | 'import-identity' | 'qr-scan' | 'recovery-phrase' | 'guardian-recovery' | 'creating-recoverable' | 'show-recovery-phrase' | 'connecting-hub' | 'ready' | 'complete';
1104
+ type OnboardingEvent = {
1105
+ type: 'AUTHENTICATE';
1106
+ } | {
1107
+ type: 'CREATE_NEW';
1108
+ } | {
1109
+ type: 'IMPORT_EXISTING';
1110
+ } | {
1111
+ type: 'PASSKEY_SUCCESS';
1112
+ identity: Identity;
1113
+ keyBundle: KeyBundle;
1114
+ } | {
1115
+ type: 'PASSKEY_FAILED';
1116
+ error: Error;
1117
+ } | {
1118
+ type: 'BROWSER_UNSUPPORTED';
1119
+ } | {
1120
+ type: 'RETRY_AUTH';
1121
+ } | {
1122
+ type: 'BACK_TO_WELCOME';
1123
+ } | {
1124
+ type: 'SCAN_QR';
1125
+ } | {
1126
+ type: 'ENTER_PHRASE';
1127
+ } | {
1128
+ type: 'IDENTITY_IMPORTED';
1129
+ identity: Identity;
1130
+ keyBundle: KeyBundle;
1131
+ } | {
1132
+ type: 'HUB_CONNECTED';
1133
+ } | {
1134
+ type: 'HUB_FAILED';
1135
+ error: Error;
1136
+ } | {
1137
+ type: 'CREATE_FIRST_PAGE';
1138
+ } | {
1139
+ type: 'CREATE_RECOVERABLE';
1140
+ } | {
1141
+ type: 'USE_SYNCED_PASSKEY';
1142
+ } | {
1143
+ type: 'ENTER_GUARDIAN_SHARES';
1144
+ } | {
1145
+ type: 'SUBMIT_GUARDIAN_SHARES';
1146
+ codes: string[];
1147
+ } | {
1148
+ type: 'SUBMIT_PHRASE';
1149
+ phrase: string;
1150
+ } | {
1151
+ type: 'IMPORT_FAILED';
1152
+ error: Error;
1153
+ } | {
1154
+ type: 'RECOVERABLE_CREATED';
1155
+ identity: Identity;
1156
+ keyBundle: KeyBundle;
1157
+ phrase: string;
1158
+ } | {
1159
+ type: 'PHRASE_SAVED';
1160
+ };
1161
+ type OnboardingMachineContext = {
1162
+ identity: Identity | null;
1163
+ keyBundle: KeyBundle | null;
1164
+ hubUrl: string | null;
1165
+ error: Error | null;
1166
+ isDemo: boolean;
1167
+ /** The recovery phrase to show once, after creating a recoverable identity (0243). */
1168
+ recoveryPhrase: string | null;
1169
+ };
1170
+ type OnboardingReducerState = {
1171
+ state: OnboardingState;
1172
+ context: OnboardingMachineContext;
1173
+ };
1174
+ declare function onboardingReducer(current: OnboardingReducerState, event: OnboardingEvent): OnboardingReducerState;
1175
+ declare function createInitialState(hubUrl?: string): OnboardingReducerState;
1176
+
1177
+ /**
1178
+ * @xnetjs/react/onboarding - React context provider for the onboarding flow
1179
+ */
1180
+
1181
+ type OnboardingContextValue = {
1182
+ state: OnboardingState;
1183
+ context: OnboardingMachineContext;
1184
+ send: (event: OnboardingEvent) => void;
1185
+ };
1186
+ type OnboardingProviderProps = {
1187
+ children: ReactNode;
1188
+ /** Default hub URL for new users */
1189
+ defaultHubUrl?: string;
1190
+ /** Called when onboarding completes */
1191
+ onComplete?: (identity: Identity, keyBundle: KeyBundle) => void;
1192
+ };
1193
+ declare function OnboardingProvider({ children, defaultHubUrl, onComplete }: OnboardingProviderProps): JSX.Element;
1194
+ /**
1195
+ * Access the onboarding state machine from within an OnboardingProvider.
1196
+ */
1197
+ declare function useOnboarding(): OnboardingContextValue;
1198
+
1199
+ type HubConnectScreenProps = {
1200
+ /** Optional: attempt hub connection. If not provided, auto-advances. */
1201
+ connectToHub?: () => Promise<void>;
1202
+ };
1203
+ declare function HubConnectScreen({ connectToHub }: HubConnectScreenProps): JSX.Element;
1204
+
1205
+ interface OnboardingFlowProps {
1206
+ /** Optional hub connection function */
1207
+ connectToHub?: HubConnectScreenProps['connectToHub'];
1208
+ /** Render prop for the completed state (app content) */
1209
+ children?: React.ReactNode;
1210
+ }
1211
+ /**
1212
+ * Renders the correct onboarding screen based on state machine state.
1213
+ *
1214
+ * @example
1215
+ * <OnboardingProvider onComplete={handleComplete}>
1216
+ * <OnboardingFlow>
1217
+ * <App />
1218
+ * </OnboardingFlow>
1219
+ * </OnboardingProvider>
1220
+ */
1221
+ declare function OnboardingFlow({ connectToHub, children }: OnboardingFlowProps): JSX.Element;
1222
+
1223
+ declare function WelcomeScreen(): JSX.Element;
1224
+
1225
+ declare function AuthenticatingScreen(): JSX.Element;
1226
+
1227
+ declare function AuthErrorScreen(): JSX.Element;
1228
+
1229
+ declare function UnsupportedBrowserScreen(): JSX.Element;
1230
+
1231
+ declare function ImportIdentityScreen(): JSX.Element;
1232
+
1233
+ declare function ReadyScreen(): JSX.Element;
1234
+
1235
+ declare function SmartWelcome(): JSX.Element;
1236
+
1237
+ /**
1238
+ * Sync progress overlay — shown during initial sync on a new device.
1239
+ */
1240
+
1241
+ interface SyncProgressOverlayProps {
1242
+ progress: SyncProgress;
1243
+ onComplete: () => void;
1244
+ }
1245
+ declare function SyncProgressOverlay({ progress, onComplete }: SyncProgressOverlayProps): JSX.Element;
1246
+
1247
+ /**
1248
+ * @xnetjs/react/onboarding - Quick-start content templates
1249
+ */
1250
+ interface QuickStartTemplate {
1251
+ id: string;
1252
+ name: string;
1253
+ description: string;
1254
+ icon: string;
1255
+ }
1256
+ declare const QUICK_START_TEMPLATES: QuickStartTemplate[];
1257
+
1258
+ /**
1259
+ * @xnetjs/react/onboarding - Helper utilities
1260
+ */
1261
+ /**
1262
+ * Get a human-friendly name for the platform's biometric authenticator.
1263
+ */
1264
+ declare function getPlatformAuthName(): string;
1265
+ /**
1266
+ * Truncate a DID for display, showing first and last segments.
1267
+ * e.g. "did:key:z6MkhaXg...yz" → "did:key:z6Mkha...xyz"
1268
+ */
1269
+ declare function truncateDid(did: string, headLen?: number, tailLen?: number): string;
1270
+ /**
1271
+ * Copy text to clipboard, returns true on success.
1272
+ * Returns false in SSR environments where navigator is unavailable.
1273
+ */
1274
+ declare function copyToClipboard(text: string): Promise<boolean>;
1275
+
1276
+ type PageTasksPanelProps = {
1277
+ pageId: string;
1278
+ };
1279
+ declare function PageTasksPanel({ pageId }: PageTasksPanelProps): JSX$1.Element;
1280
+
1281
+ /**
1282
+ * @xnetjs/react - Embedded task collection renderer
1283
+ */
1284
+
1285
+ type TaskCollectionEmbedProps = {
1286
+ currentPageId: string | null;
1287
+ currentDid: string | null;
1288
+ scope: 'current-page' | 'all';
1289
+ assignee: 'any' | 'me';
1290
+ dueDate: 'any' | 'overdue' | 'today' | 'next-7-days' | 'none';
1291
+ status: 'open' | 'done' | 'all';
1292
+ showHierarchy: boolean;
1293
+ };
1294
+ declare function TaskCollectionEmbed({ currentPageId, currentDid, scope, assignee, dueDate, status, showHierarchy }: TaskCollectionEmbedProps): JSX$1.Element;
1295
+
1296
+ /**
1297
+ * Security context for multi-level cryptography.
1298
+ *
1299
+ * Provides global security configuration and state management for:
1300
+ * - Security level selection (0, 1, 2)
1301
+ * - Verification policy configuration
1302
+ * - PQ key registry access
1303
+ * - Key bundle management
1304
+ */
1305
+
1306
+ /**
1307
+ * Security context state.
1308
+ */
1309
+ interface SecurityContextState {
1310
+ /** Current security level for new signatures */
1311
+ level: SecurityLevel;
1312
+ /** Minimum level to accept during verification */
1313
+ minVerificationLevel: SecurityLevel;
1314
+ /** Verification policy */
1315
+ verificationPolicy: 'strict' | 'permissive';
1316
+ /** PQ key registry */
1317
+ registry: PQKeyRegistry;
1318
+ /** Current key bundle (if available) */
1319
+ keyBundle?: HybridKeyBundle;
1320
+ }
1321
+ /**
1322
+ * Security context actions.
1323
+ */
1324
+ interface SecurityContextActions {
1325
+ /** Set the signing security level */
1326
+ setLevel: (level: SecurityLevel) => void;
1327
+ /** Set the minimum verification level */
1328
+ setMinVerificationLevel: (level: SecurityLevel) => void;
1329
+ /** Set the verification policy */
1330
+ setVerificationPolicy: (policy: 'strict' | 'permissive') => void;
1331
+ /** Update the key bundle */
1332
+ setKeyBundle: (bundle: HybridKeyBundle | undefined) => void;
1333
+ }
1334
+ /**
1335
+ * Combined security context value.
1336
+ */
1337
+ type SecurityContextValue = SecurityContextState & SecurityContextActions;
1338
+ /**
1339
+ * Security provider props.
1340
+ */
1341
+ interface SecurityProviderProps {
1342
+ children: ReactNode;
1343
+ /** Initial security level (default: 0 for Ed25519-only) */
1344
+ level?: SecurityLevel;
1345
+ /** Initial minimum verification level (default: 0) */
1346
+ minVerificationLevel?: SecurityLevel;
1347
+ /** Initial verification policy (default: 'strict') */
1348
+ verificationPolicy?: 'strict' | 'permissive';
1349
+ /** PQ key registry (default: MemoryPQKeyRegistry) */
1350
+ registry?: PQKeyRegistry;
1351
+ /** Initial key bundle */
1352
+ keyBundle?: HybridKeyBundle;
1353
+ }
1354
+ /**
1355
+ * Security provider component.
1356
+ *
1357
+ * Wraps the application with security configuration and state.
1358
+ *
1359
+ * @example
1360
+ * ```tsx
1361
+ * <SecurityProvider level={1} verificationPolicy="strict">
1362
+ * <App />
1363
+ * </SecurityProvider>
1364
+ * ```
1365
+ */
1366
+ declare function SecurityProvider({ children, level: initialLevel, minVerificationLevel: initialMinLevel, verificationPolicy: initialPolicy, registry: providedRegistry, keyBundle: initialBundle }: SecurityProviderProps): JSX.Element;
1367
+ /**
1368
+ * Hook to access security context.
1369
+ *
1370
+ * @throws Error if used outside of SecurityProvider
1371
+ *
1372
+ * @example
1373
+ * ```tsx
1374
+ * function MyComponent() {
1375
+ * const { level, setLevel, registry } = useSecurityContext()
1376
+ * // ...
1377
+ * }
1378
+ * ```
1379
+ */
1380
+ declare function useSecurityContext(): SecurityContextValue;
1381
+ /**
1382
+ * Hook to optionally access security context.
1383
+ *
1384
+ * Returns null if used outside of SecurityProvider (no error thrown).
1385
+ */
1386
+ declare function useSecurityContextOptional(): SecurityContextValue | null;
1387
+
1388
+ /**
1389
+ * useSecurity - Hook for security-aware operations.
1390
+ *
1391
+ * Provides signing and verification functions that use the current
1392
+ * security level from the SecurityContext.
1393
+ */
1394
+
1395
+ /**
1396
+ * Options for useSecurity hook.
1397
+ */
1398
+ interface UseSecurityOptions {
1399
+ /** Override default security level for this hook instance */
1400
+ level?: SecurityLevel;
1401
+ }
1402
+ /**
1403
+ * Return type for useSecurity hook.
1404
+ */
1405
+ interface UseSecurityResult {
1406
+ /** Current security level (from context or override) */
1407
+ level: SecurityLevel;
1408
+ /** Whether the current key bundle has PQ keys */
1409
+ hasPQKeys: boolean;
1410
+ /** Maximum level supported by current keys (0 if no PQ keys, 2 if PQ keys present) */
1411
+ maxLevel: SecurityLevel;
1412
+ /** Sign data at current security level */
1413
+ sign: (data: Uint8Array) => UnifiedSignature;
1414
+ /** Verify a signature against a DID */
1415
+ verify: (data: Uint8Array, signature: UnifiedSignature, did: DID) => Promise<VerificationResult$1>;
1416
+ /** Set the global security level */
1417
+ setLevel: (level: SecurityLevel) => void;
1418
+ /** Check if a level is supported by current keys */
1419
+ canSignAt: (level: SecurityLevel) => boolean;
1420
+ /** Check if key bundle is available */
1421
+ hasKeyBundle: boolean;
1422
+ }
1423
+ /**
1424
+ * Hook for security-aware operations.
1425
+ *
1426
+ * Provides signing and verification functions that use the current
1427
+ * security level from the SecurityContext.
1428
+ *
1429
+ * @example
1430
+ * ```tsx
1431
+ * function SignedMessage() {
1432
+ * const { sign, verify, level, hasPQKeys } = useSecurity()
1433
+ *
1434
+ * const handleSign = async () => {
1435
+ * const data = new TextEncoder().encode('Hello')
1436
+ * const sig = sign(data)
1437
+ * console.log(`Signed at Level ${sig.level}`)
1438
+ * }
1439
+ *
1440
+ * return (
1441
+ * <div>
1442
+ * <p>Security Level: {level}</p>
1443
+ * <p>PQ Keys: {hasPQKeys ? 'Yes' : 'No'}</p>
1444
+ * <button onClick={handleSign}>Sign</button>
1445
+ * </div>
1446
+ * )
1447
+ * }
1448
+ * ```
1449
+ *
1450
+ * @example Per-operation level override
1451
+ * ```tsx
1452
+ * function HighSecurityOperation() {
1453
+ * const { sign } = useSecurity({ level: 2 }) // Force Level 2
1454
+ *
1455
+ * const handleCritical = () => {
1456
+ * const data = new TextEncoder().encode('Critical operation')
1457
+ * const sig = sign(data) // Signs at Level 2
1458
+ * console.log(sig.level) // 2
1459
+ * }
1460
+ *
1461
+ * return <button onClick={handleCritical}>Critical Action</button>
1462
+ * }
1463
+ * ```
1464
+ *
1465
+ * @example Fast mode for high-frequency operations
1466
+ * ```tsx
1467
+ * function CursorUpdates() {
1468
+ * const { sign } = useSecurity({ level: 0 }) // Fast Ed25519-only
1469
+ *
1470
+ * const handleCursor = (position: number) => {
1471
+ * const data = new TextEncoder().encode(JSON.stringify({ position }))
1472
+ * const sig = sign(data) // Fast signing
1473
+ * }
1474
+ *
1475
+ * return <canvas onMouseMove={(e) => handleCursor(e.clientX)} />
1476
+ * }
1477
+ * ```
1478
+ */
1479
+ declare function useSecurity(options?: UseSecurityOptions): UseSecurityResult;
1480
+
1481
+ /**
1482
+ * Plugin registry context
1483
+ */
1484
+ declare const PluginRegistryContext: react.Context<PluginRegistry | null>;
1485
+ /**
1486
+ * Access the PluginRegistry instance
1487
+ *
1488
+ * @example
1489
+ * ```tsx
1490
+ * const registry = usePluginRegistry()
1491
+ * const plugins = registry.getAll()
1492
+ * ```
1493
+ *
1494
+ * @throws Error if used outside of XNetProvider with plugins enabled
1495
+ */
1496
+ declare function usePluginRegistry(): PluginRegistry;
1497
+ /**
1498
+ * Safely access the PluginRegistry instance, returns null if not available
1499
+ *
1500
+ * Use this when you need to optionally access the plugin system without throwing.
1501
+ */
1502
+ declare function usePluginRegistryOptional(): PluginRegistry | null;
1503
+ /**
1504
+ * Get all registered plugins with reactive updates
1505
+ *
1506
+ * @example
1507
+ * ```tsx
1508
+ * const plugins = usePlugins()
1509
+ * // Re-renders when plugins change
1510
+ * ```
1511
+ */
1512
+ declare function usePlugins(): RegisteredPlugin[];
1513
+ /**
1514
+ * Contribution type to interface mapping
1515
+ */
1516
+ type ContributionTypeMap = {
1517
+ views: ViewContribution;
1518
+ commands: CommandContribution;
1519
+ slashCommands: SlashCommandContribution;
1520
+ sidebar: SidebarContribution;
1521
+ editor: EditorContribution;
1522
+ propertyHandlers: PropertyHandlerContribution;
1523
+ blocks: BlockContribution;
1524
+ settings: SettingContribution;
1525
+ importers: ImporterContribution;
1526
+ };
1527
+ /**
1528
+ * Get contributions of a specific type with reactive updates
1529
+ *
1530
+ * @example
1531
+ * ```tsx
1532
+ * // Get all registered views
1533
+ * const views = useContributions('views')
1534
+ *
1535
+ * // Get all commands
1536
+ * const commands = useContributions('commands')
1537
+ * ```
1538
+ */
1539
+ declare function useContributions<K extends keyof ContributionTypeMap>(type: K): ContributionTypeMap[K][];
1540
+ /**
1541
+ * Get all registered views
1542
+ */
1543
+ declare function useViews(): ViewContribution[];
1544
+ /**
1545
+ * Get all registered commands
1546
+ */
1547
+ declare function useCommands(): CommandContribution[];
1548
+ /**
1549
+ * Get all registered slash commands
1550
+ */
1551
+ declare function useSlashCommands(): SlashCommandContribution[];
1552
+ /**
1553
+ * Get all registered sidebar items
1554
+ */
1555
+ declare function useSidebarItems(): SidebarContribution[];
1556
+ /**
1557
+ * Get all registered importer contributions (exploration 0189).
1558
+ *
1559
+ * Pair with `resolveImporters`/`importerAdapters` from `@xnetjs/plugins` to merge
1560
+ * plugin-contributed importers with a built-in set (e.g. the social importers).
1561
+ */
1562
+ declare function useImporters(): ImporterContribution[];
1563
+ /**
1564
+ * Get all registered editor extensions
1565
+ *
1566
+ * @throws Error if plugin system is not enabled
1567
+ */
1568
+ declare function useEditorExtensions(): EditorContribution[];
1569
+ /**
1570
+ * Get all registered editor extensions, returns empty array if plugin system is not available
1571
+ *
1572
+ * Safe version that doesn't throw if plugins aren't enabled.
1573
+ */
1574
+ declare function useEditorExtensionsSafe(): EditorContribution[];
1575
+ /**
1576
+ * Get a specific view by type
1577
+ */
1578
+ declare function useView(type: string): ViewContribution | undefined;
1579
+ /**
1580
+ * Get a specific command by ID
1581
+ */
1582
+ declare function useCommand(id: string): CommandContribution | undefined;
1583
+
1584
+ export { summarizeReactionNode as $, type AddCommentOptions as A, selectPublicInteractionMode as B, type CommentThread as C, summarizeModerationLabel as D, summarizePublicInteractionPolicy as E, type CommentVisibility as F, type FirstContactMode as G, type ModeratedCommentThread as H, type InteractionPermission as I, type ModerationFilterOptions as J, type ModerationLabelSummary as K, type PublicInteractionMode as L, type ModeratedCommentNode as M, type PublicInteractionPolicySnapshot as N, type PublicInteractionSurface as O, type PageTaskInput as P, type PublicModerationMode as Q, type ReplyContext as R, type UseModeratedThreadOptions as S, type TaskProjectionInput as T, type UseTaskProjectionSyncResult as U, type UseVisibleCommentsOptions as V, type UseVisibleCommentsResult as W, usePolicyFilteredReactionCounters as X, createReactionCounterSnapshot as Y, dedupeReactions as Z, isReactionVisible as _, type TaskTreeItem as a, type RemoteSchemaDefinition as a$, type AddReactionOptions as a0, type ReactionCounterSnapshot as a1, type ReactionNode as a2, type ReactionType as a3, type UsePolicyFilteredReactionCountersOptions as a4, type UsePolicyFilteredReactionCountersResult as a5, useMessageRequests as a6, createConversationKey as a7, createMessageRequestProperties as a8, evaluateFirstContactDecision as a9, type UseBlameResult as aA, useVerification as aB, type UseVerificationResult as aC, useHubStatus as aD, useCan as aE, type UseCanResult as aF, useCanEdit as aG, type UseCanEditResult as aH, describeGrantConsent as aI, useGrants as aJ, type GrantConsentSummary as aK, type GrantInput as aL, type UseGrantsResult as aM, summarizeAuthTrace as aN, useAuthTrace as aO, type AuthTraceSummary as aP, type UseAuthTraceResult as aQ, useBackup as aR, type UseBackupReturn as aS, useFileUpload as aT, type FileRef as aU, type UseFileUploadReturn as aV, useHubSearch as aW, type HubSearchOptions as aX, type HubSearchResult as aY, type HubSearchState as aZ, useRemoteSchema as a_, findLatestMessageRequest as aa, hasAcceptedContact as ab, summarizeMessageRequest as ac, type CreateMessageRequestOptions as ad, type FirstContactAdmission as ae, type FirstContactDecision as af, type FirstContactDecisionInput as ag, type FirstContactVisibility as ah, type MessageRequestNode as ai, type MessageRequestProperties as aj, type MessageRequestStatus as ak, type UseMessageRequestsOptions as al, type UseMessageRequestsResult as am, useCommentCount as an, useCommentCounts as ao, useHistory as ap, type UseHistoryResult as aq, useUndo as ar, type UseUndoResult as as, type UseUndoOptions as at, useAudit as au, type UseAuditResult as av, type UseAuditOptions as aw, useDiff as ax, type UseDiffResult as ay, useBlame as az, type UseFindOptions as b, useViews as b$, type RemoteSchemaState as b0, usePeerDiscovery as b1, type DiscoveredPeer as b2, HubStatusIndicator as b3, Skeleton as b4, injectSkeletonStyles as b5, type SkeletonProps as b6, DemoBanner as b7, type DemoBannerProps as b8, DemoQuotaIndicator as b9, type OnboardingContextValue as bA, type OnboardingFlowProps as bB, type OnboardingState as bC, type OnboardingEvent as bD, type OnboardingMachineContext as bE, type OnboardingReducerState as bF, type QuickStartTemplate as bG, type SyncProgressOverlayProps as bH, PageTasksPanel as bI, type PageTasksPanelProps as bJ, TaskCollectionEmbed as bK, type TaskCollectionEmbedProps as bL, SecurityProvider as bM, useSecurityContext as bN, useSecurityContextOptional as bO, type SecurityContextState as bP, type SecurityContextActions as bQ, type SecurityContextValue as bR, type SecurityProviderProps as bS, useSecurity as bT, type UseSecurityOptions as bU, type UseSecurityResult as bV, PluginRegistryContext as bW, usePluginRegistry as bX, usePluginRegistryOptional as bY, usePlugins as bZ, useContributions as b_, type DemoQuotaIndicatorProps as ba, DemoDataExpiredScreen as bb, useDemoMode as bc, type DemoModeState as bd, type DemoLimits as be, type DemoUsage as bf, useSyncManager as bg, OnboardingProvider as bh, useOnboarding as bi, OnboardingFlow as bj, WelcomeScreen as bk, AuthenticatingScreen as bl, AuthErrorScreen as bm, UnsupportedBrowserScreen as bn, ImportIdentityScreen as bo, HubConnectScreen as bp, ReadyScreen as bq, SmartWelcome as br, SyncProgressOverlay as bs, onboardingReducer as bt, createInitialState as bu, QUICK_START_TEMPLATES as bv, getPlatformAuthName as bw, truncateDid as bx, copyToClipboard as by, type OnboardingProviderProps as bz, type UseFindResult as c, useCommands as c0, useSlashCommands as c1, useSidebarItems as c2, useImporters as c3, useEditorExtensions as c4, useEditorExtensionsSafe as c5, useView as c6, useCommand as c7, usePageTaskSync as d, type PageTaskReferenceInput as e, type UsePageTaskSyncOptions as f, type UsePageTaskSyncResult as g, useTaskProjectionSync as h, type TaskProjectionReferenceInput as i, type TaskProjectionHost as j, type UseTaskProjectionSyncOptions as k, useTasks as l, type UseTasksOptions as m, type UseTasksResult as n, useComments as o, type UseCommentsOptions as p, type UseCommentsResult as q, type CommentNode as r, useVisibleComments as s, useModeratedThread as t, useFind as u, createModerationLabelIndex as v, evaluateCommentModeration as w, evaluateInteractionPermission as x, moderateThread as y, selectActiveInteractionPolicy as z };