@nivaro/react 0.1.89 → 0.1.91

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/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { CascadeFilterRule } from '@nivaro/sdk';
2
+ import { Context } from 'react';
2
3
  import { default as default_2 } from 'react';
3
4
  import { FieldDependencyConfig } from '@nivaro/sdk';
4
5
  import { ImportParseResponse } from '@nivaro/sdk';
@@ -617,6 +618,20 @@ export declare function CollectionImportPanel({ initialJobId, onJobOpen }: {
617
618
  onJobOpen?: (id: string | null) => void;
618
619
  }): JSX.Element;
619
620
 
621
+ /**
622
+ * Realtime sprint client contract. A HOST (admin, efp-new) owns the actual
623
+ * Socket.io connection and provides this to shared components; components
624
+ * that render without it degrade to polling exactly as before — the context
625
+ * is always optional.
626
+ */
627
+ export declare interface CollectionUpdateEvent {
628
+ collection: string;
629
+ item: string | number;
630
+ action?: 'create' | 'update' | 'delete';
631
+ changed_fields?: string[];
632
+ _seq?: number;
633
+ }
634
+
620
635
  export declare interface Column<T = Record<string, unknown>> {
621
636
  key: string;
622
637
  header: React_2.ReactNode;
@@ -681,6 +696,8 @@ export declare function ConformanceView({ className }: {
681
696
  className?: string;
682
697
  }): JSX.Element;
683
698
 
699
+ export declare function createLeaderSocket(key: string, cbs: LeaderCallbacks): LeaderSocketHandle;
700
+
684
701
  export declare function DataTable<T = Record<string, unknown>>({ columns, rows, rowKey, total, page, limit, isLoading, isError, errorMessage, sort, onSortChange, onPageChange, onRowClick, onRowContextMenu, searchValue, onSearchChange, searchPlaceholder, filterDefs, filterValues, onFilterChange, toolbarRight, emptyMessage, minBodyHeight, fillHeight, hideFilterRow, nowrapCells, density, pinFirstColumn, columnPins, onColumnPinChange, columnFilterRow, hScrollProxy, selectedIds, onSelectionChange, rowClassName, rowGroups, collapsedGroups, onToggleGroup }: DataTableProps<T>): React_2.JSX.Element;
685
702
 
686
703
  export declare interface DataTableProps<T = Record<string, unknown>> {
@@ -1608,11 +1625,13 @@ export declare type ItemLinkTarget = {
1608
1625
  layoutSlug?: string | null;
1609
1626
  };
1610
1627
 
1611
- export declare function ItemLockBanner({ lockHolder, onTakeOver, takingOver, isAdmin }: {
1628
+ export declare function ItemLockBanner({ lockHolder, onTakeOver, takingOver, isAdmin, onRequestLock, requesting }: {
1612
1629
  lockHolder: LockHolder | null;
1613
1630
  onTakeOver: () => void;
1614
1631
  takingOver: boolean;
1615
1632
  isAdmin?: boolean;
1633
+ onRequestLock?: () => void;
1634
+ requesting?: boolean;
1616
1635
  }): JSX.Element | null;
1617
1636
 
1618
1637
  export declare function JsonMapEditor({ config, scope }: {
@@ -1749,6 +1768,35 @@ declare interface LayoutGroup {
1749
1768
 
1750
1769
  export declare type LayoutItem = FormGroupDescriptor | '__ungrouped__';
1751
1770
 
1771
+ declare interface LeaderCallbacks {
1772
+ /** Called when this tab becomes leader — create the real socket, wire onAny → deliver. */
1773
+ becomeLeader(deliver: (event: string, payload: any) => void, emit: {
1774
+ current: (event: string, payload: any) => void;
1775
+ }): void;
1776
+ /** Called when this tab loses/abdicates leadership — tear the socket down. */
1777
+ resignLeader(): void;
1778
+ }
1779
+
1780
+ /**
1781
+ * Tab leader election (#277): with many tabs open, only ONE holds the real
1782
+ * Socket.io connection; the rest ride a BroadcastChannel. Halves server socket
1783
+ * load and keeps events consistent across tabs.
1784
+ *
1785
+ * Election: localStorage heartbeat lock (`nvr-sock-leader:<key>` = "id:ts").
1786
+ * The leader refreshes its claim every 2s; followers watch for staleness
1787
+ * (>6s) and race to claim it. BroadcastChannel carries events leader→followers
1788
+ * and emit requests follower→leader. No BroadcastChannel (old browser,
1789
+ * cross-origin iframe) → every tab is its own leader, the historic behaviour.
1790
+ */
1791
+ export declare interface LeaderSocketHandle {
1792
+ isLeader(): boolean;
1793
+ /** Fires on every inbound socket event (leader: direct; follower: relayed). */
1794
+ onEvent(cb: (event: string, payload: any) => void): () => void;
1795
+ /** Emit toward the server (follower forwards to the leader). */
1796
+ emit(event: string, payload?: any): void;
1797
+ destroy(): void;
1798
+ }
1799
+
1752
1800
  declare interface LockHolder {
1753
1801
  locked_by: string;
1754
1802
  locked_by_name: string | null;
@@ -2541,6 +2589,17 @@ export declare interface ReadViewLayout {
2541
2589
  assignments: LayoutAssignment[];
2542
2590
  }
2543
2591
 
2592
+ export declare interface RealtimeAdapter {
2593
+ /** Subscribe to collection:update for the named collections. Returns unsubscribe. */
2594
+ subscribeCollections(collections: string[], cb: (ev: CollectionUpdateEvent) => void): () => void;
2595
+ /** Listen to an arbitrary socket event (lock:requested, record:uploading…). */
2596
+ on(event: string, cb: (payload: any) => void): () => void;
2597
+ /** Emit an event to the server (record:uploading, record:join…). */
2598
+ emit(event: string, payload?: any): void;
2599
+ }
2600
+
2601
+ export declare const RealtimeContext: Context<RealtimeAdapter | null>;
2602
+
2544
2603
  export declare function RecordChatActions({ collection, itemDraft }: {
2545
2604
  collection: string;
2546
2605
  itemDraft: Record<string, unknown>;
@@ -3147,6 +3206,8 @@ export declare function useItemLock(collection: string | undefined, item: string
3147
3206
  takeOver: () => Promise<void>;
3148
3207
  takingOver: boolean;
3149
3208
  isAdmin: boolean;
3209
+ requestLock: () => Promise<void>;
3210
+ requesting: boolean;
3150
3211
  };
3151
3212
 
3152
3213
  /** Resolved item-link helpers honoring the host's itemUrl/openItem overrides. */
@@ -3237,8 +3298,17 @@ export declare type UseNivaroFormReturn = {
3237
3298
  gridFlushersRef: default_2.MutableRefObject<Map<string, () => Promise<void>>>;
3238
3299
  };
3239
3300
 
3301
+ /**
3302
+ * Online-user set for presence dots in user pickers (#284). One shared
3303
+ * 30s-polled query per app (react-query dedupes); consumers get a Set of
3304
+ * user ids. Fails to an empty set — a picker must never break on presence.
3305
+ */
3306
+ export declare function useOnlineUsers(enabled?: boolean): Set<string>;
3307
+
3240
3308
  export declare function useOptionalNivaroClient(): NivaroClient | null;
3241
3309
 
3310
+ export declare function useOptionalRealtime(): RealtimeAdapter | null;
3311
+
3242
3312
  export declare function useOrderedLayout(form: UseNivaroFormReturn): {
3243
3313
  items: LayoutItem[];
3244
3314
  hasTabs: boolean;