@xnetjs/react 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +52 -1
  2. package/dist/index.js +122 -37
  3. package/package.json +10 -10
package/dist/index.d.ts CHANGED
@@ -710,6 +710,57 @@ interface UseGridDatabaseResult {
710
710
  }
711
711
  declare function useGridDatabase(databaseId: string, options?: UseGridDatabaseOptions): UseGridDatabaseResult;
712
712
 
713
+ /**
714
+ * The entangle bus (exploration 0346, Phase 3) — page-scoped hover/select
715
+ * co-presence between frames.
716
+ *
717
+ * Frames on one page share a bus: hovering a row in a database frame
718
+ * lights the same node's pin in a map frame and its wikilink in the
719
+ * prose (Embark's "Entangler"). Cheap by construction: per-node
720
+ * subscriptions through useSyncExternalStore, so only the components
721
+ * whose highlight state actually changes re-render.
722
+ *
723
+ * Absent a provider every hook degrades to a no-op, so views adopt the
724
+ * bus unconditionally and stay correct on bus-less surfaces.
725
+ */
726
+
727
+ declare class EntangleBus {
728
+ private hovered;
729
+ private selected;
730
+ private listeners;
731
+ setHovered(nodeId: string, on: boolean): void;
732
+ setSelected(nodeIds: readonly string[]): void;
733
+ isHovered(nodeId: string): boolean;
734
+ isSelected(nodeId: string): boolean;
735
+ /** All currently highlighted ids (hovered ∪ selected) — for canvas
736
+ * renderers (map layers) that filter rather than subscribe per id. */
737
+ snapshotHighlighted(): string[];
738
+ subscribe: (listener: () => void) => (() => void);
739
+ private notify;
740
+ }
741
+ /** One bus per page surface — mount around the page's frames. */
742
+ declare function EntangleProvider({ children }: {
743
+ children: ReactNode;
744
+ }): JSX.Element;
745
+ /** The surrounding bus, or null on bus-less surfaces. */
746
+ declare function useEntangleBus(): EntangleBus | null;
747
+ /**
748
+ * Whether this node is entangle-highlighted (hovered or selected in a
749
+ * sibling frame). Subscribes per node id — only affected rows/pins
750
+ * re-render on hover changes.
751
+ */
752
+ declare function useEntangledHighlight(nodeId: string | null | undefined): boolean;
753
+ /** Publish hover on/off for a node id (no-op without a bus). */
754
+ declare function usePublishEntangleHover(): (nodeId: string, on: boolean) => void;
755
+ /**
756
+ * Convenience bind: spread onto a row/card/chip element to publish its
757
+ * node's hover state.
758
+ */
759
+ declare function useEntangleBind(nodeId: string | null | undefined): {
760
+ onMouseEnter?: () => void;
761
+ onMouseLeave?: () => void;
762
+ };
763
+
713
764
  /**
714
765
  * useTimeMachine — React binding for the Time Machine (exploration 0329 P1).
715
766
  *
@@ -989,4 +1040,4 @@ declare function flattenTaskTree(items: TaskTreeItem[], depth?: number): Rendera
989
1040
  declare function formatTaskDueDate(timestamp: number | undefined): string | null;
990
1041
  declare function isTaskOverdue(timestamp: number | undefined, completed: boolean): boolean;
991
1042
 
992
- export { type AddRowOptions, type CanvasTaskInput, type CheckoutOptions, type DraftReview, type DraftReviewCard, type DraftReviewMember, FlatNode, type GridFieldModel, type GridOptionModel, type GridRowModel, type GridViewConfigPatch, type GridViewModel, type PresenceAwareness, type PresencePeer, QueryFilter, type RenderableTaskRow, type SavedViewCanvasProjectionNode, type SavedViewDateBrushSelection, type SavedViewDateBucketFieldSummary, type SavedViewDateBucketInterval, type SavedViewDateBucketSummary, type SavedViewFacetSelection, type SavedViewFacetSummary, type SavedViewFacetValueSummary, type SavedViewFeedEnrichmentAdapter, type SavedViewFeedEnrichmentEntry, type SavedViewInspectorItem, type SavedViewInspectorItemKind, type SavedViewLensDraft, type SavedViewPresentationMode, type SavedViewPrivacyChip, type SavedViewPrivacyChipTone, type SavedViewPrivacySummary, type SavedViewQueryOverride, type SavedViewQueryResult, SavedViewResultTable, type SavedViewResultTableProps, type SavedViewRowInspectorModel, SavedViewRunner, type SavedViewRunnerProps, type SavedViewSchemaRegistry, type SavedViewSortDirection, type SavedViewVisualCanvasProjectionRequest, SavedViewVisualFeed, type SavedViewVisualLayoutId, type SavedViewVisualLayoutOption, type SavedViewVisualPreviewCreator, type SavedViewVisualPreviewKind, type SavedViewVisualPreviewModel, type SavedViewVisualPreviewPrivacy, type SavedViewVisualPreviewRelationship, type SavedViewVisualTimelineBucket, type SavedViewVisualWorkspaceLayout, TaskProjectionInput, TaskTreeItem, type UseBillingResult, type UseCanCreateResult, type UseCanvasTaskSyncOptions, type UseCanvasTaskSyncResult, type UseDraftResult, type UseEffectiveSchemaResult, type UseGlobalUndoResult, type UseGridDatabaseOptions, type UseGridDatabaseResult, type UsePresenceOptions, type UsePresenceResult, type UseSavedViewOptions, type UseSavedViewResult, UseTaskProjectionSyncResult, type UseTimeMachineOptions, type UseTimeMachineResult, createSavedViewCanvasProjectionNodes, createSavedViewLensDraft, createSavedViewVisualCanvasProjectionRequest, createSavedViewVisualPreviewFingerprint, deriveCachedSavedViewVisualPreviews, deriveSavedViewColumns, deriveSavedViewDateBucketSummaries, deriveSavedViewFacetSummaries, deriveSavedViewPrivacyChips, deriveSavedViewRowInspector, deriveSavedViewTimelineBuckets, deriveSavedViewVisualPreview, deriveSavedViewVisualPreviews, filterSavedViewRowsByDateBrush, filterSavedViewRowsByFacets, flattenTaskTree, formatSavedViewCellValue, formatTaskDueDate, getSavedViewSensitiveResultWarning, hasSavedViewVisualPreviewSensitiveData, isSavedViewVisualPreviewEmbeddable, isTaskOverdue, mergeSavedViewFeedEnrichment, savedViewVisualPreviewIsSelfActor, useBilling, useCanCreate, useCanvasTaskSync, useDraft, useEffectiveSchema, useGlobalUndo, useGridDatabase, usePresence, useSavedView, useTimeMachine };
1043
+ export { type AddRowOptions, type CanvasTaskInput, type CheckoutOptions, type DraftReview, type DraftReviewCard, type DraftReviewMember, EntangleBus, EntangleProvider, FlatNode, type GridFieldModel, type GridOptionModel, type GridRowModel, type GridViewConfigPatch, type GridViewModel, type PresenceAwareness, type PresencePeer, QueryFilter, type RenderableTaskRow, type SavedViewCanvasProjectionNode, type SavedViewDateBrushSelection, type SavedViewDateBucketFieldSummary, type SavedViewDateBucketInterval, type SavedViewDateBucketSummary, type SavedViewFacetSelection, type SavedViewFacetSummary, type SavedViewFacetValueSummary, type SavedViewFeedEnrichmentAdapter, type SavedViewFeedEnrichmentEntry, type SavedViewInspectorItem, type SavedViewInspectorItemKind, type SavedViewLensDraft, type SavedViewPresentationMode, type SavedViewPrivacyChip, type SavedViewPrivacyChipTone, type SavedViewPrivacySummary, type SavedViewQueryOverride, type SavedViewQueryResult, SavedViewResultTable, type SavedViewResultTableProps, type SavedViewRowInspectorModel, SavedViewRunner, type SavedViewRunnerProps, type SavedViewSchemaRegistry, type SavedViewSortDirection, type SavedViewVisualCanvasProjectionRequest, SavedViewVisualFeed, type SavedViewVisualLayoutId, type SavedViewVisualLayoutOption, type SavedViewVisualPreviewCreator, type SavedViewVisualPreviewKind, type SavedViewVisualPreviewModel, type SavedViewVisualPreviewPrivacy, type SavedViewVisualPreviewRelationship, type SavedViewVisualTimelineBucket, type SavedViewVisualWorkspaceLayout, TaskProjectionInput, TaskTreeItem, type UseBillingResult, type UseCanCreateResult, type UseCanvasTaskSyncOptions, type UseCanvasTaskSyncResult, type UseDraftResult, type UseEffectiveSchemaResult, type UseGlobalUndoResult, type UseGridDatabaseOptions, type UseGridDatabaseResult, type UsePresenceOptions, type UsePresenceResult, type UseSavedViewOptions, type UseSavedViewResult, UseTaskProjectionSyncResult, type UseTimeMachineOptions, type UseTimeMachineResult, createSavedViewCanvasProjectionNodes, createSavedViewLensDraft, createSavedViewVisualCanvasProjectionRequest, createSavedViewVisualPreviewFingerprint, deriveCachedSavedViewVisualPreviews, deriveSavedViewColumns, deriveSavedViewDateBucketSummaries, deriveSavedViewFacetSummaries, deriveSavedViewPrivacyChips, deriveSavedViewRowInspector, deriveSavedViewTimelineBuckets, deriveSavedViewVisualPreview, deriveSavedViewVisualPreviews, filterSavedViewRowsByDateBrush, filterSavedViewRowsByFacets, flattenTaskTree, formatSavedViewCellValue, formatTaskDueDate, getSavedViewSensitiveResultWarning, hasSavedViewVisualPreviewSensitiveData, isSavedViewVisualPreviewEmbeddable, isTaskOverdue, mergeSavedViewFeedEnrichment, savedViewVisualPreviewIsSelfActor, useBilling, useCanCreate, useCanvasTaskSync, useDraft, useEffectiveSchema, useEntangleBind, useEntangleBus, useEntangledHighlight, useGlobalUndo, useGridDatabase, usePresence, usePublishEntangleHover, useSavedView, useTimeMachine };
package/dist/index.js CHANGED
@@ -5001,6 +5001,85 @@ function useGridDatabase(databaseId, options = {}) {
5001
5001
  };
5002
5002
  }
5003
5003
 
5004
+ // src/hooks/useEntangle.tsx
5005
+ import {
5006
+ createContext,
5007
+ useCallback as useCallback4,
5008
+ useContext,
5009
+ useMemo as useMemo6,
5010
+ useSyncExternalStore
5011
+ } from "react";
5012
+ import { jsx as jsx3 } from "react/jsx-runtime";
5013
+ var EntangleBus = class {
5014
+ hovered = /* @__PURE__ */ new Set();
5015
+ selected = /* @__PURE__ */ new Set();
5016
+ listeners = /* @__PURE__ */ new Set();
5017
+ setHovered(nodeId, on) {
5018
+ if (on === this.hovered.has(nodeId)) return;
5019
+ if (on) this.hovered.add(nodeId);
5020
+ else this.hovered.delete(nodeId);
5021
+ this.notify();
5022
+ }
5023
+ setSelected(nodeIds) {
5024
+ this.selected = new Set(nodeIds);
5025
+ this.notify();
5026
+ }
5027
+ isHovered(nodeId) {
5028
+ return this.hovered.has(nodeId);
5029
+ }
5030
+ isSelected(nodeId) {
5031
+ return this.selected.has(nodeId);
5032
+ }
5033
+ /** All currently highlighted ids (hovered ∪ selected) — for canvas
5034
+ * renderers (map layers) that filter rather than subscribe per id. */
5035
+ snapshotHighlighted() {
5036
+ return [.../* @__PURE__ */ new Set([...this.hovered, ...this.selected])];
5037
+ }
5038
+ subscribe = (listener) => {
5039
+ this.listeners.add(listener);
5040
+ return () => this.listeners.delete(listener);
5041
+ };
5042
+ notify() {
5043
+ for (const listener of this.listeners) listener();
5044
+ }
5045
+ };
5046
+ var EntangleContext = createContext(null);
5047
+ function EntangleProvider({ children }) {
5048
+ const bus = useMemo6(() => new EntangleBus(), []);
5049
+ return /* @__PURE__ */ jsx3(EntangleContext.Provider, { value: bus, children });
5050
+ }
5051
+ function useEntangleBus() {
5052
+ return useContext(EntangleContext);
5053
+ }
5054
+ var noopSubscribe = () => () => {
5055
+ };
5056
+ function useEntangledHighlight(nodeId) {
5057
+ const bus = useContext(EntangleContext);
5058
+ return useSyncExternalStore(
5059
+ bus ? bus.subscribe : noopSubscribe,
5060
+ () => bus && nodeId ? bus.isHovered(nodeId) || bus.isSelected(nodeId) : false
5061
+ );
5062
+ }
5063
+ function usePublishEntangleHover() {
5064
+ const bus = useContext(EntangleContext);
5065
+ return useCallback4(
5066
+ (nodeId, on) => {
5067
+ bus?.setHovered(nodeId, on);
5068
+ },
5069
+ [bus]
5070
+ );
5071
+ }
5072
+ function useEntangleBind(nodeId) {
5073
+ const bus = useContext(EntangleContext);
5074
+ return useMemo6(() => {
5075
+ if (!bus || !nodeId) return {};
5076
+ return {
5077
+ onMouseEnter: () => bus.setHovered(nodeId, true),
5078
+ onMouseLeave: () => bus.setHovered(nodeId, false)
5079
+ };
5080
+ }, [bus, nodeId]);
5081
+ }
5082
+
5004
5083
  // src/hooks/useTimeMachine.ts
5005
5084
  import { CHECKPOINT_SCHEMA_IRI } from "@xnetjs/data";
5006
5085
  import {
@@ -5013,11 +5092,11 @@ import {
5013
5092
  listCheckpoints,
5014
5093
  restoreToFrontier
5015
5094
  } from "@xnetjs/history";
5016
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo6, useRef as useRef5, useState as useState7 } from "react";
5095
+ import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo7, useRef as useRef5, useState as useState7 } from "react";
5017
5096
  function useTimeMachine(nodeId, options) {
5018
5097
  const { store, isReady } = useNodeStore();
5019
5098
  const memberKey = options?.memberIds?.join(",") ?? "";
5020
- const members = useMemo6(() => {
5099
+ const members = useMemo7(() => {
5021
5100
  if (!nodeId) return [];
5022
5101
  const extra = options?.memberIds ?? [];
5023
5102
  return [nodeId, ...extra.filter((id) => id !== nodeId)];
@@ -5034,7 +5113,7 @@ function useTimeMachine(nodeId, options) {
5034
5113
  const [preview, setPreview] = useState7(null);
5035
5114
  const [diffs, setDiffs] = useState7([]);
5036
5115
  const engineRef = useRef5(null);
5037
- const getEngines = useCallback4(() => {
5116
+ const getEngines = useCallback5(() => {
5038
5117
  if (!store) return null;
5039
5118
  const storage = store.getStorageAdapter();
5040
5119
  if (!storage) return null;
@@ -5048,7 +5127,7 @@ function useTimeMachine(nodeId, options) {
5048
5127
  }
5049
5128
  return engineRef.current;
5050
5129
  }, [store]);
5051
- const reload = useCallback4(async () => {
5130
+ const reload = useCallback5(async () => {
5052
5131
  if (!nodeId || !isReady || !store) return;
5053
5132
  const engines = getEngines();
5054
5133
  if (!engines) return;
@@ -5132,7 +5211,7 @@ function useTimeMachine(nodeId, options) {
5132
5211
  cancelled = true;
5133
5212
  };
5134
5213
  }, [nodeId, timeline, position, getEngines]);
5135
- const setPosition = useCallback4(
5214
+ const setPosition = useCallback5(
5136
5215
  (index) => {
5137
5216
  const max = timeline.length - 1;
5138
5217
  const clamped = Math.max(0, Math.min(index, max));
@@ -5140,10 +5219,10 @@ function useTimeMachine(nodeId, options) {
5140
5219
  },
5141
5220
  [timeline.length]
5142
5221
  );
5143
- const stepBack = useCallback4(() => setPosition(position - 1), [setPosition, position]);
5144
- const stepForward = useCallback4(() => setPosition(position + 1), [setPosition, position]);
5145
- const goToLatest = useCallback4(() => setRawPosition(null), []);
5146
- const createNamedVersion = useCallback4(
5222
+ const stepBack = useCallback5(() => setPosition(position - 1), [setPosition, position]);
5223
+ const stepForward = useCallback5(() => setPosition(position + 1), [setPosition, position]);
5224
+ const goToLatest = useCallback5(() => setRawPosition(null), []);
5225
+ const createNamedVersion = useCallback5(
5147
5226
  async (name, note) => {
5148
5227
  if (!nodeId || !store) return null;
5149
5228
  const engines = getEngines();
@@ -5164,7 +5243,7 @@ function useTimeMachine(nodeId, options) {
5164
5243
  },
5165
5244
  [nodeId, store, members, getEngines, reload]
5166
5245
  );
5167
- const positionOfCheckpoint = useCallback4(
5246
+ const positionOfCheckpoint = useCallback5(
5168
5247
  (checkpoint) => {
5169
5248
  const frontier = checkpoint.properties.frontier;
5170
5249
  if (!frontier) return null;
@@ -5179,7 +5258,7 @@ function useTimeMachine(nodeId, options) {
5179
5258
  },
5180
5259
  [timeline]
5181
5260
  );
5182
- const frontierAt = useCallback4(
5261
+ const frontierAt = useCallback5(
5183
5262
  (index) => {
5184
5263
  const scope = getEngines()?.scope;
5185
5264
  if (!scope) return {};
@@ -5187,7 +5266,7 @@ function useTimeMachine(nodeId, options) {
5187
5266
  },
5188
5267
  [getEngines, timeline]
5189
5268
  );
5190
- const restore = useCallback4(async () => {
5269
+ const restore = useCallback5(async () => {
5191
5270
  if (!nodeId || !store || timeline.length === 0) return null;
5192
5271
  const engines = getEngines();
5193
5272
  if (!engines) return null;
@@ -5242,7 +5321,7 @@ import {
5242
5321
  refreshDraftFromMain,
5243
5322
  threeWayPropertyMerge
5244
5323
  } from "@xnetjs/history";
5245
- import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef6, useState as useState8 } from "react";
5324
+ import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef6, useState as useState8 } from "react";
5246
5325
  var baseIRI = (schemaId) => schemaId.split("@")[0];
5247
5326
  async function resolveMembers(store, hostId) {
5248
5327
  const members = [hostId];
@@ -5269,7 +5348,7 @@ function useDraft(hostId) {
5269
5348
  const [loading, setLoading] = useState8(false);
5270
5349
  const [error, setError] = useState8(null);
5271
5350
  const engineRef = useRef6(null);
5272
- const getEngines = useCallback5(() => {
5351
+ const getEngines = useCallback6(() => {
5273
5352
  if (!store) return null;
5274
5353
  const storage = store.getStorageAdapter();
5275
5354
  if (!storage) return null;
@@ -5285,7 +5364,7 @@ function useDraft(hostId) {
5285
5364
  return engineRef.current;
5286
5365
  }, [store]);
5287
5366
  const draftIdsRef = useRef6(/* @__PURE__ */ new Set());
5288
- const reload = useCallback5(async () => {
5367
+ const reload = useCallback6(async () => {
5289
5368
  if (!hostId || !isReady || !store) return;
5290
5369
  setLoading(true);
5291
5370
  setError(null);
@@ -5324,7 +5403,7 @@ function useDraft(hostId) {
5324
5403
  unsubOverlay();
5325
5404
  };
5326
5405
  }, [store, hostId, reload]);
5327
- const checkout = useCallback5(
5406
+ const checkout = useCallback6(
5328
5407
  async (draftId) => {
5329
5408
  if (!hostId || !store) return false;
5330
5409
  const engines = getEngines();
@@ -5358,11 +5437,11 @@ function useDraft(hostId) {
5358
5437
  },
5359
5438
  [hostId, store, getEngines, reload]
5360
5439
  );
5361
- const returnToMain = useCallback5(() => {
5440
+ const returnToMain = useCallback6(() => {
5362
5441
  if (!store) return;
5363
5442
  store.setCheckedOutDraft(null);
5364
5443
  }, [store]);
5365
- const createDraft = useCallback5(
5444
+ const createDraft = useCallback6(
5366
5445
  async (name) => {
5367
5446
  if (!hostId || !store) return null;
5368
5447
  try {
@@ -5376,7 +5455,7 @@ function useDraft(hostId) {
5376
5455
  },
5377
5456
  [hostId, store, checkout]
5378
5457
  );
5379
- const discard = useCallback5(
5458
+ const discard = useCallback6(
5380
5459
  async (draftId) => {
5381
5460
  if (!store) return false;
5382
5461
  const engines = getEngines();
@@ -5395,7 +5474,7 @@ function useDraft(hostId) {
5395
5474
  },
5396
5475
  [store, getEngines, reload]
5397
5476
  );
5398
- const merge = useCallback5(
5477
+ const merge = useCallback6(
5399
5478
  async (draftId) => {
5400
5479
  if (!store) return null;
5401
5480
  const engines = getEngines();
@@ -5414,7 +5493,7 @@ function useDraft(hostId) {
5414
5493
  },
5415
5494
  [store, getEngines, reload]
5416
5495
  );
5417
- const refresh = useCallback5(
5496
+ const refresh = useCallback6(
5418
5497
  async (draftId) => {
5419
5498
  if (!store) return null;
5420
5499
  const engines = getEngines();
@@ -5430,7 +5509,7 @@ function useDraft(hostId) {
5430
5509
  },
5431
5510
  [store, getEngines, reload]
5432
5511
  );
5433
- const setReviewRequested = useCallback5(
5512
+ const setReviewRequested = useCallback6(
5434
5513
  async (draftId, requested) => {
5435
5514
  if (!store) return;
5436
5515
  try {
@@ -5441,7 +5520,7 @@ function useDraft(hostId) {
5441
5520
  },
5442
5521
  [store]
5443
5522
  );
5444
- const computeReview = useCallback5(
5523
+ const computeReview = useCallback6(
5445
5524
  async (draftId) => {
5446
5525
  if (!store) return null;
5447
5526
  const engines = getEngines();
@@ -5525,26 +5604,26 @@ function useDraft(hostId) {
5525
5604
  }
5526
5605
 
5527
5606
  // src/hooks/useGlobalUndo.ts
5528
- import { useCallback as useCallback6, useContext, useEffect as useEffect9, useReducer } from "react";
5607
+ import { useCallback as useCallback7, useContext as useContext2, useEffect as useEffect9, useReducer } from "react";
5529
5608
  function readUndoContext(ctx) {
5530
5609
  if (!ctx) return { undoManager: null, nodeStore: null };
5531
5610
  return { undoManager: ctx.undoManager, nodeStore: ctx.nodeStore };
5532
5611
  }
5533
5612
  function useGlobalUndo() {
5534
- const ctx = useContext(XNetContext);
5613
+ const ctx = useContext2(XNetContext);
5535
5614
  const { undoManager, nodeStore } = readUndoContext(ctx);
5536
5615
  const [, bump] = useReducer((n) => n + 1, 0);
5537
5616
  useEffect9(() => {
5538
5617
  if (!nodeStore) return;
5539
5618
  return nodeStore.subscribe(() => bump());
5540
5619
  }, [nodeStore]);
5541
- const undo = useCallback6(async () => {
5620
+ const undo = useCallback7(async () => {
5542
5621
  if (!undoManager) return false;
5543
5622
  const ok = await undoManager.undoLatest();
5544
5623
  bump();
5545
5624
  return ok;
5546
5625
  }, [undoManager]);
5547
- const redo = useCallback6(async () => {
5626
+ const redo = useCallback7(async () => {
5548
5627
  if (!undoManager) return false;
5549
5628
  const ok = await undoManager.redoLatest();
5550
5629
  bump();
@@ -5559,7 +5638,7 @@ function useGlobalUndo() {
5559
5638
  }
5560
5639
 
5561
5640
  // src/hooks/useCanCreate.ts
5562
- import { useEffect as useEffect10, useMemo as useMemo7, useRef as useRef7, useState as useState9 } from "react";
5641
+ import { useEffect as useEffect10, useMemo as useMemo8, useRef as useRef7, useState as useState9 } from "react";
5563
5642
  var INITIAL_STATE = {
5564
5643
  canCreate: false,
5565
5644
  loading: true,
@@ -5569,7 +5648,7 @@ function useCanCreate(schemaId, properties) {
5569
5648
  const { store, isReady } = useNodeStore();
5570
5649
  const [state, setState] = useState9(INITIAL_STATE);
5571
5650
  const requestRef = useRef7(0);
5572
- const propertiesKey = useMemo7(() => JSON.stringify(properties ?? {}), [properties]);
5651
+ const propertiesKey = useMemo8(() => JSON.stringify(properties ?? {}), [properties]);
5573
5652
  useEffect10(() => {
5574
5653
  if (!store || !isReady) {
5575
5654
  setState((prev) => ({ ...prev, loading: true }));
@@ -5639,7 +5718,7 @@ import {
5639
5718
  } from "@xnetjs/runtime";
5640
5719
 
5641
5720
  // src/hooks/useBilling.ts
5642
- import { useCallback as useCallback7, useContext as useContext2, useEffect as useEffect11, useMemo as useMemo8, useState as useState10 } from "react";
5721
+ import { useCallback as useCallback8, useContext as useContext3, useEffect as useEffect11, useMemo as useMemo9, useState as useState10 } from "react";
5643
5722
  var toHttpUrl = (hubUrl) => {
5644
5723
  try {
5645
5724
  const url = new URL(hubUrl);
@@ -5675,21 +5754,21 @@ function deriveBilling(state) {
5675
5754
  };
5676
5755
  }
5677
5756
  function useBilling() {
5678
- const context = useContext2(XNetContext);
5757
+ const context = useContext3(XNetContext);
5679
5758
  const [state, setState] = useState10(null);
5680
5759
  const [loading, setLoading] = useState10(
5681
5760
  Boolean(context?.hubUrl || context?.billing?.apiBase)
5682
5761
  );
5683
5762
  const [error, setError] = useState10(null);
5684
- const apiBase = useMemo8(() => {
5763
+ const apiBase = useMemo9(() => {
5685
5764
  if (context?.billing?.apiBase) return context.billing.apiBase.replace(/\/$/, "");
5686
5765
  return context?.hubUrl ? toHttpUrl(context.hubUrl) : null;
5687
5766
  }, [context?.billing?.apiBase, context?.hubUrl]);
5688
- const authHeaders = useCallback7(async () => {
5767
+ const authHeaders = useCallback8(async () => {
5689
5768
  const token = context?.getHubAuthToken ? await context.getHubAuthToken() : "";
5690
5769
  return token ? { Authorization: `Bearer ${token}` } : {};
5691
5770
  }, [context]);
5692
- const reload = useCallback7(async () => {
5771
+ const reload = useCallback8(async () => {
5693
5772
  if (!apiBase) {
5694
5773
  setState(null);
5695
5774
  setLoading(false);
@@ -5710,7 +5789,7 @@ function useBilling() {
5710
5789
  useEffect11(() => {
5711
5790
  void reload();
5712
5791
  }, [reload]);
5713
- const redirectVia = useCallback7(
5792
+ const redirectVia = useCallback8(
5714
5793
  async (path, body) => {
5715
5794
  if (!apiBase) throw new Error("Hub URL not configured");
5716
5795
  const res = await fetch(`${apiBase}${path}`, {
@@ -5724,11 +5803,11 @@ function useBilling() {
5724
5803
  },
5725
5804
  [apiBase, authHeaders]
5726
5805
  );
5727
- const openCheckout = useCallback7(
5806
+ const openCheckout = useCallback8(
5728
5807
  (priceRef, options = {}) => redirectVia("/billing/checkout", buildCheckoutBody(priceRef, options)),
5729
5808
  [redirectVia]
5730
5809
  );
5731
- const openPortal = useCallback7(
5810
+ const openPortal = useCallback8(
5732
5811
  (returnUrl) => redirectVia("/billing/portal", returnUrl ? { returnUrl } : {}),
5733
5812
  [redirectVia]
5734
5813
  );
@@ -5753,6 +5832,8 @@ export {
5753
5832
  DemoBanner,
5754
5833
  DemoDataExpiredScreen,
5755
5834
  DemoQuotaIndicator,
5835
+ EntangleBus,
5836
+ EntangleProvider,
5756
5837
  ErrorBoundary,
5757
5838
  HubConnectScreen,
5758
5839
  HubStatusIndicator,
@@ -5874,6 +5955,9 @@ export {
5874
5955
  useEditorExtensions,
5875
5956
  useEditorExtensionsSafe,
5876
5957
  useEffectiveSchema,
5958
+ useEntangleBind,
5959
+ useEntangleBus,
5960
+ useEntangledHighlight,
5877
5961
  useFileUpload,
5878
5962
  useFind,
5879
5963
  useGlobalUndo,
@@ -5901,6 +5985,7 @@ export {
5901
5985
  usePlugins,
5902
5986
  usePolicyFilteredReactionCounters,
5903
5987
  usePresence,
5988
+ usePublishEntangleHover,
5904
5989
  useQuery,
5905
5990
  useRelatedRows,
5906
5991
  useRemoteSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xnetjs/react",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,15 +46,15 @@
46
46
  "y-protocols": "^1.0.6",
47
47
  "yjs": "^13.6.24",
48
48
  "@xnetjs/billing": "0.0.2",
49
- "@xnetjs/core": "2.3.0",
50
- "@xnetjs/crypto": "2.3.0",
51
- "@xnetjs/data": "2.3.0",
52
- "@xnetjs/data-bridge": "2.3.0",
53
- "@xnetjs/history": "2.3.0",
54
- "@xnetjs/identity": "2.3.0",
55
- "@xnetjs/plugins": "2.3.0",
56
- "@xnetjs/runtime": "0.5.3",
57
- "@xnetjs/sync": "2.3.0"
49
+ "@xnetjs/core": "2.5.0",
50
+ "@xnetjs/crypto": "2.5.0",
51
+ "@xnetjs/data": "2.5.0",
52
+ "@xnetjs/data-bridge": "2.5.0",
53
+ "@xnetjs/history": "2.5.0",
54
+ "@xnetjs/identity": "2.5.0",
55
+ "@xnetjs/plugins": "2.5.0",
56
+ "@xnetjs/runtime": "0.5.5",
57
+ "@xnetjs/sync": "2.5.0"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "react": "^18.0.0 || ^19.0.0"