react-state-basis 0.6.1 → 0.6.2

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.js CHANGED
@@ -126,11 +126,26 @@ var calculateSpectralInfluence = (graph, maxIterations = 20, tolerance = 1e-3) =
126
126
  return scores;
127
127
  };
128
128
 
129
- // src/core/ranker.ts
129
+ // src/core/constants.ts
130
+ var WINDOW_SIZE = 50;
131
+ var SIMILARITY_THRESHOLD = 0.88;
132
+ var LOOP_THRESHOLD = 150;
133
+ var VOLATILITY_THRESHOLD = 25;
134
+ var INSTANCE_SEP = "##";
135
+
136
+ // src/core/label.ts
137
+ var stripInstance = (label) => {
138
+ const idx = label.indexOf(INSTANCE_SEP);
139
+ return idx === -1 ? label : label.slice(0, idx);
140
+ };
130
141
  var parseLabel = (label) => {
131
- const parts = label.split(" -> ");
132
- return { file: parts[0] || "Unknown", name: parts[1] || label };
142
+ const base = stripInstance(label);
143
+ const parts = base.split(" -> ");
144
+ return { file: parts[0] || "Unknown", name: parts[1] || base };
133
145
  };
146
+ var isSameField = (labelA, labelB) => stripInstance(labelA) === stripInstance(labelB);
147
+
148
+ // src/core/ranker.ts
134
149
  var identifyTopIssues = (graph, history2, redundantLabels2, violationMap) => {
135
150
  const results = [];
136
151
  const influence = calculateSpectralInfluence(graph);
@@ -260,10 +275,6 @@ var STYLES = {
260
275
  bold: "font-weight: bold;",
261
276
  label: "background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;"
262
277
  };
263
- var parseLabel2 = (label) => {
264
- const parts = label.split(" -> ");
265
- return { file: parts[0] || "Unknown", name: parts[1] || label };
266
- };
267
278
  var shouldLog = (key) => {
268
279
  const now = Date.now();
269
280
  const last = LAST_LOG_TIMES.get(key) || 0;
@@ -286,7 +297,7 @@ var getSuggestedFix = (issue, info) => {
286
297
  return `Local state is 'shadowing' Global Context. This creates two sources of truth. Delete the local state and consume the %cContext%c value directly.`;
287
298
  }
288
299
  if (leaks.length > 0) {
289
- const targetName = parseLabel2(leaks[0].target).name;
300
+ const targetName = parseLabel(leaks[0].target).name;
290
301
  if (issue.label.includes("effect")) {
291
302
  return `This Effect triggers a synchronous re-render of ${targetName}. Calculate ${targetName} during the render phase (Derived State) or wrap in %cuseMemo%c if expensive.`;
292
303
  }
@@ -316,7 +327,7 @@ var displayHealthReport = (history2, threshold, violationMap) => {
316
327
  `font-weight: normal; color: ${THEME.muted}; font-style: italic;`
317
328
  );
318
329
  topIssues.forEach((issue, idx) => {
319
- const info = parseLabel2(issue.label);
330
+ const info = parseLabel(issue.label);
320
331
  const icon = issue.metric === "influence" ? "\u26A1" : "\u{1F4C8}";
321
332
  const pColor = idx === 0 ? THEME.problem : idx === 1 ? THEME.solution : THEME.identity;
322
333
  let displayName = info.name;
@@ -336,7 +347,7 @@ var displayHealthReport = (history2, threshold, violationMap) => {
336
347
  const byFile = /* @__PURE__ */ new Map();
337
348
  issue.violations.forEach((v) => {
338
349
  if (issue.label.includes("Global Event") && v.type === "context_mirror") return;
339
- const { file, name } = parseLabel2(v.target);
350
+ const { file, name } = parseLabel(v.target);
340
351
  if (!byFile.has(file)) byFile.set(file, []);
341
352
  byFile.get(file).push(name);
342
353
  });
@@ -411,7 +422,7 @@ var displayHealthReport = (history2, threshold, violationMap) => {
411
422
  const clusterMetas = cluster.map((l) => ({
412
423
  label: l,
413
424
  meta: history2.get(l),
414
- name: parseLabel2(l).name
425
+ name: parseLabel(l).name
415
426
  }));
416
427
  const hasCtx = clusterMetas.some(
417
428
  (c) => c.meta.role === "context" /* CONTEXT */ || c.meta.role === "store" /* STORE */
@@ -452,8 +463,8 @@ var displayHealthReport = (history2, threshold, violationMap) => {
452
463
  };
453
464
  var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
454
465
  if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;
455
- const infoA = parseLabel2(labelA);
456
- const infoB = parseLabel2(labelB);
466
+ const infoA = parseLabel(labelA);
467
+ const infoB = parseLabel(labelB);
457
468
  const isContextMirror = metaA.role === "local" /* LOCAL */ && metaB.role === "context" /* CONTEXT */ || metaB.role === "local" /* LOCAL */ && metaA.role === "context" /* CONTEXT */;
458
469
  const isStoreMirror = metaA.role === "local" /* LOCAL */ && metaB.role === "store" /* STORE */ || metaB.role === "local" /* LOCAL */ && metaA.role === "store" /* STORE */;
459
470
  const alertType = isContextMirror ? "CONTEXT MIRRORING" : isStoreMirror ? "STORE MIRRORING" : "DUPLICATE STATE";
@@ -498,8 +509,8 @@ var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
498
509
  };
499
510
  var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
500
511
  if (!isWeb || !shouldLog(`causal-${sourceLabel}-${targetLabel}`)) return;
501
- const target = parseLabel2(targetLabel);
502
- const source = parseLabel2(sourceLabel);
512
+ const target = parseLabel(targetLabel);
513
+ const source = parseLabel(sourceLabel);
503
514
  const headerType = sourceMeta.role === "context" /* CONTEXT */ ? "CONTEXT SYNC LEAK" : sourceMeta.role === "store" /* STORE */ ? "STORE SYNC LEAK" : "DOUBLE RENDER";
504
515
  const isEffect = sourceLabel.includes("effect") || sourceLabel.includes("useLayoutEffect");
505
516
  console.groupCollapsed(`%c \u26A1 BASIS | ${headerType} `, STYLES.headerProblem);
@@ -530,10 +541,10 @@ var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
530
541
  };
531
542
  var displayViolentBreaker = (label, count, threshold) => {
532
543
  if (!isWeb) return;
533
- const parts = label.split(" -> ");
544
+ const { name } = parseLabel(label);
534
545
  console.group(`%c \u{1F6D1} BASIS CRITICAL | CIRCUIT BREAKER `, STYLES.headerProblem);
535
546
  console.error(`INFINITE LOOP DETECTED
536
- Variable: ${parts[1] || label}
547
+ Variable: ${name}
537
548
  Frequency: ${count} updates/sec`);
538
549
  console.log(`%cACTION: Update BLOCKED to prevent browser freeze.`, `color: ${THEME.problem}; font-weight: bold;`);
539
550
  console.groupEnd();
@@ -543,12 +554,6 @@ var displayBootLog = (windowSize) => {
543
554
  console.log(`%cBasis%cAuditor%c "Graph Era" (Window: ${windowSize})`, STYLES.basis, STYLES.version, `color: ${THEME.muted}; font-style: italic; margin-left: 8px;`);
544
555
  };
545
556
 
546
- // src/core/constants.ts
547
- var WINDOW_SIZE = 50;
548
- var SIMILARITY_THRESHOLD = 0.88;
549
- var LOOP_THRESHOLD = 150;
550
- var VOLATILITY_THRESHOLD = 25;
551
-
552
557
  // src/core/analysis.ts
553
558
  var CAUSAL_MARGIN = 0.05;
554
559
  var isEventDriven = (label, graph) => {
@@ -585,6 +590,7 @@ var calculateAllSimilarities = (entryA, entryB) => {
585
590
  };
586
591
  var shouldSkipComparison = (entryA, entryB, dirtyLabels2) => {
587
592
  if (entryA.label === entryB.label) return true;
593
+ if (isSameField(entryA.label, entryB.label)) return true;
588
594
  if (dirtyLabels2.has(entryB.label) && entryA.label > entryB.label) return true;
589
595
  return false;
590
596
  };
@@ -920,39 +926,52 @@ if (typeof window !== "undefined") {
920
926
  // src/hooks.ts
921
927
  var anonCount = 0;
922
928
  var getFallbackLabel = (type) => `anon_${type}_${anonCount++}`;
929
+ var reactUseId = React.useId;
930
+ var legacyInstanceCounter = 0;
931
+ var useInstanceId = () => {
932
+ const [legacyId] = (0, import_react.useState)(
933
+ () => typeof reactUseId === "function" ? "" : `legacy_${legacyInstanceCounter++}`
934
+ );
935
+ return typeof reactUseId === "function" ? reactUseId() : legacyId;
936
+ };
937
+ var withInstance = (label, instanceId) => `${label}${INSTANCE_SEP}${instanceId}`;
923
938
  var React19 = React;
924
939
  function useState(initialState, label) {
925
940
  const [val, setVal] = (0, import_react.useState)(initialState);
926
941
  const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("state")).current;
942
+ const instanceId = useInstanceId();
943
+ const storageKey = withInstance(effectiveLabel, instanceId);
927
944
  (0, import_react.useEffect)(() => {
928
- registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
945
+ registerVariable(storageKey, { role: "local" /* LOCAL */ });
929
946
  return () => {
930
- unregisterVariable(effectiveLabel);
947
+ unregisterVariable(storageKey);
931
948
  };
932
- }, [effectiveLabel]);
949
+ }, [storageKey]);
933
950
  const setter = (0, import_react.useCallback)((value) => {
934
- if (recordUpdate(effectiveLabel)) {
951
+ if (recordUpdate(storageKey)) {
935
952
  setVal(value);
936
953
  }
937
- }, [effectiveLabel]);
954
+ }, [storageKey]);
938
955
  return [val, setter];
939
956
  }
940
957
  function useReducer(reducer, initialArg, init, label) {
941
958
  const isLazy = typeof init === "function";
942
959
  const providedLabel = label || (typeof init === "string" ? init : void 0);
943
960
  const effectiveLabel = (0, import_react.useRef)(providedLabel || getFallbackLabel("reducer")).current;
961
+ const instanceId = useInstanceId();
962
+ const storageKey = withInstance(effectiveLabel, instanceId);
944
963
  const [state, dispatch] = isLazy ? (0, import_react.useReducer)(reducer, initialArg, init) : (0, import_react.useReducer)(reducer, initialArg);
945
964
  (0, import_react.useEffect)(() => {
946
- registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
965
+ registerVariable(storageKey, { role: "local" /* LOCAL */ });
947
966
  return () => {
948
- unregisterVariable(effectiveLabel);
967
+ unregisterVariable(storageKey);
949
968
  };
950
- }, [effectiveLabel]);
969
+ }, [storageKey]);
951
970
  const basisDispatch = (0, import_react.useCallback)((action) => {
952
- if (recordUpdate(effectiveLabel)) {
971
+ if (recordUpdate(storageKey)) {
953
972
  dispatch(action);
954
973
  }
955
- }, [effectiveLabel, dispatch]);
974
+ }, [storageKey, dispatch]);
956
975
  return [state, basisDispatch];
957
976
  }
958
977
  function createContext(defaultValue, label) {
@@ -978,28 +997,34 @@ function useContext(context) {
978
997
  }
979
998
  function useMemo(factory, deps, label) {
980
999
  const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("proj")).current;
1000
+ const instanceId = useInstanceId();
1001
+ const storageKey = withInstance(effectiveLabel, instanceId);
981
1002
  (0, import_react.useEffect)(() => {
982
- registerVariable(effectiveLabel, { role: "proj" /* PROJECTION */ });
1003
+ registerVariable(storageKey, { role: "proj" /* PROJECTION */ });
983
1004
  return () => {
984
- unregisterVariable(effectiveLabel);
1005
+ unregisterVariable(storageKey);
985
1006
  };
986
- }, [effectiveLabel]);
1007
+ }, [storageKey]);
987
1008
  return (0, import_react.useMemo)(factory, deps || []);
988
1009
  }
989
1010
  function useCallback(callback, deps, label) {
990
1011
  const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("cb")).current;
1012
+ const instanceId = useInstanceId();
1013
+ const storageKey = withInstance(effectiveLabel, instanceId);
991
1014
  (0, import_react.useEffect)(() => {
992
- registerVariable(effectiveLabel, { role: "proj" /* PROJECTION */ });
1015
+ registerVariable(storageKey, { role: "proj" /* PROJECTION */ });
993
1016
  return () => {
994
- unregisterVariable(effectiveLabel);
1017
+ unregisterVariable(storageKey);
995
1018
  };
996
- }, [effectiveLabel]);
1019
+ }, [storageKey]);
997
1020
  return (0, import_react.useCallback)(callback, deps);
998
1021
  }
999
1022
  function useEffect(effect, deps, label) {
1000
1023
  const effectiveLabel = label || "anonymous_effect";
1024
+ const instanceId = useInstanceId();
1025
+ const storageKey = withInstance(effectiveLabel, instanceId);
1001
1026
  (0, import_react.useEffect)(() => {
1002
- beginEffectTracking(effectiveLabel);
1027
+ beginEffectTracking(storageKey);
1003
1028
  const destructor = effect();
1004
1029
  endEffectTracking();
1005
1030
  return typeof destructor === "function" ? destructor : void 0;
@@ -1007,8 +1032,10 @@ function useEffect(effect, deps, label) {
1007
1032
  }
1008
1033
  function useLayoutEffect(effect, deps, label) {
1009
1034
  const effectiveLabel = label || "anonymous_layout_effect";
1035
+ const instanceId = useInstanceId();
1036
+ const storageKey = withInstance(effectiveLabel, instanceId);
1010
1037
  (0, import_react.useLayoutEffect)(() => {
1011
- beginEffectTracking(effectiveLabel);
1038
+ beginEffectTracking(storageKey);
1012
1039
  const destructor = effect();
1013
1040
  endEffectTracking();
1014
1041
  return typeof destructor === "function" ? destructor : void 0;
@@ -1016,36 +1043,40 @@ function useLayoutEffect(effect, deps, label) {
1016
1043
  }
1017
1044
  function useOptimistic(passthrough, reducer, label) {
1018
1045
  const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("optimistic")).current;
1046
+ const instanceId = useInstanceId();
1047
+ const storageKey = withInstance(effectiveLabel, instanceId);
1019
1048
  (0, import_react.useEffect)(() => {
1020
- registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
1049
+ registerVariable(storageKey, { role: "local" /* LOCAL */ });
1021
1050
  return () => {
1022
- unregisterVariable(effectiveLabel);
1051
+ unregisterVariable(storageKey);
1023
1052
  };
1024
- }, [effectiveLabel]);
1053
+ }, [storageKey]);
1025
1054
  const [state, reactAddOptimistic] = React19.useOptimistic(passthrough, reducer);
1026
1055
  const addOptimistic = (0, import_react.useCallback)((payload) => {
1027
- if (recordUpdate(effectiveLabel)) {
1056
+ if (recordUpdate(storageKey)) {
1028
1057
  reactAddOptimistic(payload);
1029
1058
  }
1030
- }, [effectiveLabel, reactAddOptimistic]);
1059
+ }, [storageKey, reactAddOptimistic]);
1031
1060
  return [state, addOptimistic];
1032
1061
  }
1033
1062
  function useActionState(action, initialState, permalink, label) {
1034
1063
  const isLabelArg = typeof permalink === "string" && label === void 0;
1035
1064
  const effectiveLabel = (0, import_react.useRef)(isLabelArg ? permalink : label || getFallbackLabel("action_state")).current;
1036
1065
  const actualPermalink = isLabelArg ? void 0 : permalink;
1066
+ const instanceId = useInstanceId();
1067
+ const storageKey = withInstance(effectiveLabel, instanceId);
1037
1068
  const [state, reactDispatch, isPending] = React19.useActionState(action, initialState, actualPermalink);
1038
1069
  (0, import_react.useEffect)(() => {
1039
- registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
1070
+ registerVariable(storageKey, { role: "local" /* LOCAL */ });
1040
1071
  return () => {
1041
- unregisterVariable(effectiveLabel);
1072
+ unregisterVariable(storageKey);
1042
1073
  };
1043
- }, [effectiveLabel]);
1074
+ }, [storageKey]);
1044
1075
  const basisDispatch = (0, import_react.useCallback)((payload) => {
1045
- if (recordUpdate(effectiveLabel)) {
1076
+ if (recordUpdate(storageKey)) {
1046
1077
  reactDispatch(payload);
1047
1078
  }
1048
- }, [effectiveLabel, reactDispatch]);
1079
+ }, [storageKey, reactDispatch]);
1049
1080
  return [state, basisDispatch, isPending];
1050
1081
  }
1051
1082
  var useRef = import_react.useRef;
@@ -1200,7 +1231,7 @@ function renderMatrix(ctx, entries) {
1200
1231
  };
1201
1232
  for (let i = head; i < L; i++) addToPath(buffer[i], uiPos++);
1202
1233
  for (let i = 0; i < head; i++) addToPath(buffer[i], uiPos++);
1203
- const stateName = label.split(" -> ")[1] || label;
1234
+ const stateName = parseLabel(label).name;
1204
1235
  const textX = L * colW + pad + 10;
1205
1236
  ctx.fillStyle = isContext ? HUD_THEME.header : isRedundant ? HUD_THEME.error : HUD_THEME.text;
1206
1237
  const prefix = meta.role === "store" ? "\u03A3 " : isContext ? "\u03A9 " : isRedundant ? "! " : "";