@burdenoff/fe-libs 2026.723.5 → 2026.725.1

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.
@@ -53,6 +53,24 @@ export interface ActiveContextProviderProps {
53
53
  tenant?: string;
54
54
  };
55
55
  }
56
+ export declare const CONTEXT_THRASH_WINDOW_MS = 500;
57
+ export declare const CONTEXT_THRASH_MAX_FLIPS = 3;
58
+ export interface ContextFieldThrashState {
59
+ current: string | null;
60
+ previous: string | null;
61
+ flips: number;
62
+ windowStart: number;
63
+ suppressUntil: number;
64
+ }
65
+ export declare function createContextFieldThrashState(initial: string | null): ContextFieldThrashState;
66
+ /**
67
+ * Decides whether `nextValue` should be applied to a context field, mutating
68
+ * `state` to reflect the decision. Returns `false` for a true no-op (value
69
+ * unchanged), while an active suppression window is in effect, or when this
70
+ * write is detected as the Nth rapid alternation back to the field's prior
71
+ * value — the ping-pong signature described above.
72
+ */
73
+ export declare function shouldApplyContextFieldWrite(fieldName: string, state: ContextFieldThrashState, nextValue: string | null, now: number): boolean;
56
74
  /**
57
75
  * ActiveContextProvider
58
76
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ActiveContextProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/shell/ActiveContextProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAiBf;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,sCAAsC;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oCAAoC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,kCAAkC;IAClC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,+BAA+B;IAC/B,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,6BAA6B;IAC7B,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,4BAA4B;IAC5B,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAE7C,qCAAqC;IACrC,UAAU,EAAE,CACV,OAAO,EAAE,OAAO,CAAC;QACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC,KACC,IAAI,CAAC;IAEV,+BAA+B;IAC/B,YAAY,EAAE,MAAM,IAAI,CAAC;IAEzB,kCAAkC;IAClC,cAAc,EAAE,OAAO,CAAC;CACzB;AAID,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,wBAAwB;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sBAAsB;IACtB,SAAS,CAAC,EAAE;QACV,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAiCD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,qBAA4B,EAC5B,kBAAyB,EACzB,gBAAuB,EACvB,eAAsB,EACtB,UAAuC,EACvC,SAAiB,EACjB,SAA6C,GAC9C,EAAE,0BAA0B,2CAkS5B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,uBAM/B"}
1
+ {"version":3,"file":"ActiveContextProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/shell/ActiveContextProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAiBf;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,sCAAsC;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oCAAoC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,kCAAkC;IAClC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,+BAA+B;IAC/B,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,6BAA6B;IAC7B,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,4BAA4B;IAC5B,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAE7C,qCAAqC;IACrC,UAAU,EAAE,CACV,OAAO,EAAE,OAAO,CAAC;QACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC,KACC,IAAI,CAAC;IAEV,+BAA+B;IAC/B,YAAY,EAAE,MAAM,IAAI,CAAC;IAEzB,kCAAkC;IAClC,cAAc,EAAE,OAAO,CAAC;CACzB;AAID,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,wBAAwB;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sBAAsB;IACtB,SAAS,CAAC,EAAE;QACV,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAgCD,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,uBAAuB,CAE7F;AAgBD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,uBAAuB,EAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,GAAG,EAAE,MAAM,GACV,OAAO,CAsCT;AAiCD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,qBAA4B,EAC5B,kBAAyB,EACzB,gBAAuB,EACvB,eAAsB,EACtB,UAAuC,EACvC,SAAiB,EACjB,SAA6C,GAC9C,EAAE,0BAA0B,2CA0X5B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,uBAM/B"}
@@ -1,32 +1,60 @@
1
1
  import { getProfileContext as e, resolveActiveProfileId as t, setProfileContext as n } from "./ProfileStorageManager.js";
2
2
  import { ACTIVE_CONTEXT_STORAGE_KEY as r, DEFAULT_ACTIVE_CONTEXT_URL_PARAMS as i, clearActiveContextStorage as a, getUrlParam as o, readActiveContextStorageValue as s, writeActiveContextFallback as c, writeActiveContextStorageValue as l } from "./ActiveContextStorage.js";
3
3
  import { isSsoNavigationPending as u } from "../../utils/ssoDeposit.js";
4
- import { createContext as d, use as f, useCallback as p, useEffect as m, useMemo as h, useState as g } from "react";
5
- import { jsx as _ } from "react/jsx-runtime";
4
+ import { createContext as d, use as f, useCallback as p, useEffect as m, useMemo as h, useRef as g, useState as _ } from "react";
5
+ import { jsx as v } from "react/jsx-runtime";
6
6
  //#region src/shared/providers/shell/ActiveContextProvider.tsx
7
- var v = d(null);
8
- function y(e) {
7
+ var y = d(null);
8
+ function b(e) {
9
+ return {
10
+ current: e,
11
+ previous: null,
12
+ flips: 0,
13
+ windowStart: 0,
14
+ suppressUntil: 0
15
+ };
16
+ }
17
+ function x() {
18
+ try {
19
+ return !!{
20
+ BASE_URL: "/",
21
+ DEV: !1,
22
+ MODE: "production",
23
+ PROD: !0,
24
+ SSR: !1
25
+ }?.DEV;
26
+ } catch {
27
+ return !1;
28
+ }
29
+ }
30
+ function S(e, t, n, r) {
31
+ if (t.current === n) return !1;
32
+ if (r < t.suppressUntil) return x() && console.warn(`[ActiveContext] Suppressing rapid ${e} change to avoid a render loop (BOFF-5395): holding at ${JSON.stringify(t.current)}, refused ${JSON.stringify(n)}.`), !1;
33
+ let i = n === t.previous, a = r - t.windowStart < 500;
34
+ return i && a ? t.flips += 1 : (t.flips = 1, t.windowStart = r), t.flips >= 3 ? (t.suppressUntil = r + 500, t.flips = 0, x() && console.warn(`[ActiveContext] Detected ${e} ping-pong between ${JSON.stringify(t.current)} and ${JSON.stringify(n)} (BOFF-5395) — holding at the current value instead of looping.`), !1) : (t.previous = t.current, t.current = n, !0);
35
+ }
36
+ function C(e) {
9
37
  if (typeof window > "u" || u() || window.location.pathname.startsWith("/auth/")) return;
10
38
  let t = new URL(window.location.href);
11
39
  Object.entries(e).forEach(([e, n]) => {
12
40
  n ? t.searchParams.set(e, n) : t.searchParams.delete(e);
13
41
  }), window.history.replaceState({}, "", t.toString());
14
42
  }
15
- function b({ children: u, defaultOrganizationId: d = null, defaultWorkspaceId: f = null, defaultProjectId: b = null, defaultTenantId: x = null, storageKey: S = r, syncToUrl: C = !1, urlParams: w = i }) {
16
- let [T, E] = g(() => {
43
+ function w({ children: u, defaultOrganizationId: d = null, defaultWorkspaceId: f = null, defaultProjectId: x = null, defaultTenantId: w = null, storageKey: T = r, syncToUrl: E = !1, urlParams: D = i }) {
44
+ let [O, k] = _(() => {
17
45
  if (typeof window > "u") return d;
18
- if (C) {
19
- let e = o(w.organization);
46
+ if (E) {
47
+ let e = o(D.organization);
20
48
  if (e) return e;
21
49
  }
22
- return s("organization", S) || d;
23
- }), [D, O] = g(() => {
50
+ return s("organization", T) || d;
51
+ }), [A, j] = _(() => {
24
52
  if (typeof window > "u") return f;
25
- if (C) {
26
- let e = o(w.workspace);
53
+ if (E) {
54
+ let e = o(D.workspace);
27
55
  if (e) return e;
28
56
  }
29
- let r = s("workspace", S) || f;
57
+ let r = s("workspace", T) || f;
30
58
  if (r) {
31
59
  let i = t();
32
60
  if (i) {
@@ -38,145 +66,152 @@ function b({ children: u, defaultOrganizationId: d = null, defaultWorkspaceId: f
38
66
  }
39
67
  }
40
68
  return r;
41
- }), [k, A] = g(() => {
42
- if (typeof window > "u") return b;
43
- if (C) {
44
- let e = o(w.project);
69
+ }), [M, N] = _(() => {
70
+ if (typeof window > "u") return x;
71
+ if (E) {
72
+ let e = o(D.project);
45
73
  if (e) return e;
46
74
  }
47
- return s("project", S) || b;
48
- }), [j, M] = g(() => {
49
- if (typeof window > "u") return x;
50
- if (C) {
51
- let e = o(w.tenant);
75
+ return s("project", T) || x;
76
+ }), [P, F] = _(() => {
77
+ if (typeof window > "u") return w;
78
+ if (E) {
79
+ let e = o(D.tenant);
52
80
  if (e) return e;
53
81
  }
54
- return s("tenant", S) || x;
55
- });
56
- m(() => {
57
- l("organization", T, S), l("workspace", D, S), l("project", k, S), l("tenant", j, S);
82
+ return s("tenant", T) || w;
83
+ }), I = g(null);
84
+ I.current === null && (I.current = b(O));
85
+ let L = g(null);
86
+ L.current === null && (L.current = b(A));
87
+ let R = g(null);
88
+ R.current === null && (R.current = b(M));
89
+ let z = g(null);
90
+ z.current === null && (z.current = b(P)), m(() => {
91
+ l("organization", O, T), l("workspace", A, T), l("project", M, T), l("tenant", P, T);
58
92
  }, [
59
- T,
60
- D,
61
- k,
62
- j,
63
- S
93
+ O,
94
+ A,
95
+ M,
96
+ P,
97
+ T
64
98
  ]), m(() => {
65
99
  let r = t();
66
100
  if (!r) return;
67
101
  let i = e(r), a = {
68
102
  ...i,
69
- organizationId: T,
70
- workspaceId: D,
71
- projectId: k,
72
- tenantId: j
103
+ organizationId: O,
104
+ workspaceId: A,
105
+ projectId: M,
106
+ tenantId: P
73
107
  };
74
108
  i?.organizationId === a.organizationId && i?.workspaceId === a.workspaceId && i?.projectId === a.projectId && i?.tenantId === a.tenantId || n(r, a);
75
109
  }, [
76
- T,
77
- D,
78
- k,
79
- j
110
+ O,
111
+ A,
112
+ M,
113
+ P
80
114
  ]), m(() => {
81
- C && y({
82
- [w.organization]: T,
83
- [w.workspace]: D,
84
- [w.project]: k,
85
- [w.tenant]: j
115
+ E && C({
116
+ [D.organization]: O,
117
+ [D.workspace]: A,
118
+ [D.project]: M,
119
+ [D.tenant]: P
86
120
  });
87
121
  }, [
88
- T,
89
- D,
90
- k,
91
- j,
92
- C,
93
- w
122
+ O,
123
+ A,
124
+ M,
125
+ P,
126
+ E,
127
+ D
94
128
  ]), m(() => {
95
- if (!C) return;
129
+ if (!E) return;
96
130
  let e = () => {
97
- let e = o(w.organization), t = o(w.workspace), n = o(w.project), r = o(w.tenant);
98
- e !== T && E(e), t !== D && O(t), n !== k && A(n), r !== j && M(r);
131
+ let e = o(D.organization), t = o(D.workspace), n = o(D.project), r = o(D.tenant);
132
+ e !== O && (k(e), I.current.previous = I.current.current, I.current.current = e), t !== A && (j(t), L.current.previous = L.current.current, L.current.current = t), n !== M && (N(n), R.current.previous = R.current.current, R.current.current = n), r !== P && (F(r), z.current.previous = z.current.current, z.current.current = r);
99
133
  };
100
134
  return window.addEventListener("popstate", e), () => window.removeEventListener("popstate", e);
101
135
  }, [
102
- C,
103
- w,
104
- T,
136
+ E,
105
137
  D,
106
- k,
107
- j
138
+ O,
139
+ A,
140
+ M,
141
+ P
108
142
  ]);
109
- let N = p((r) => {
110
- E(r);
143
+ let B = p((r) => {
144
+ if (!S("organizationId", I.current, r, Date.now())) return;
145
+ k(r);
111
146
  let i = t();
112
147
  i && n(i, {
113
148
  ...e(i),
114
149
  organizationId: r
115
150
  }), typeof window < "u" && window.dispatchEvent(new CustomEvent("burdenoff:organization-changed", { detail: { organizationId: r } }));
116
- }, []), P = p((r, i) => {
151
+ }, []), V = p((r, i) => {
117
152
  let a = {
118
153
  organization: "organizationId",
119
154
  workspace: "workspaceId",
120
155
  project: "projectId",
121
156
  tenant: "tenantId"
122
157
  };
123
- l(r, i, S);
158
+ l(r, i, T);
124
159
  let o = t();
125
160
  o ? n(o, {
126
161
  ...e(o),
127
162
  [a[r]]: i
128
- }) : typeof window < "u" && c(r, i, S);
129
- }, [S]), F = p((e) => {
130
- O(e), P("workspace", e), typeof window < "u" && window.dispatchEvent(new CustomEvent("burdenoff:workspace-changed", { detail: { workspaceId: e } }));
131
- }, [P]), I = p((e) => {
132
- A(e), P("project", e), typeof window < "u" && window.dispatchEvent(new CustomEvent("burdenoff:project-changed", { detail: { projectId: e } }));
133
- }, [P]), L = p((e) => {
134
- M(e), P("tenant", e);
135
- }, [P]), R = p((e) => {
136
- e.organizationId !== void 0 && N(e.organizationId), e.workspaceId !== void 0 && F(e.workspaceId), e.projectId !== void 0 && I(e.projectId), e.tenantId !== void 0 && L(e.tenantId);
163
+ }) : typeof window < "u" && c(r, i, T);
164
+ }, [T]), H = p((e) => {
165
+ S("workspaceId", L.current, e, Date.now()) && (j(e), V("workspace", e), typeof window < "u" && window.dispatchEvent(new CustomEvent("burdenoff:workspace-changed", { detail: { workspaceId: e } })));
166
+ }, [V]), U = p((e) => {
167
+ S("projectId", R.current, e, Date.now()) && (N(e), V("project", e), typeof window < "u" && window.dispatchEvent(new CustomEvent("burdenoff:project-changed", { detail: { projectId: e } })));
168
+ }, [V]), W = p((e) => {
169
+ S("tenantId", z.current, e, Date.now()) && (F(e), V("tenant", e));
170
+ }, [V]), G = p((e) => {
171
+ e.organizationId !== void 0 && B(e.organizationId), e.workspaceId !== void 0 && H(e.workspaceId), e.projectId !== void 0 && U(e.projectId), e.tenantId !== void 0 && W(e.tenantId);
137
172
  }, [
138
- N,
139
- F,
140
- I,
141
- L
142
- ]), z = p(() => {
143
- E(null), O(null), A(null), M(null), a(S);
173
+ B,
174
+ H,
175
+ U,
176
+ W
177
+ ]), K = p(() => {
178
+ k(null), j(null), N(null), F(null), I.current = b(null), L.current = b(null), R.current = b(null), z.current = b(null), a(T);
144
179
  let e = t();
145
180
  e && n(e, {});
146
- }, [S]), B = h(() => ({
147
- organizationId: T,
148
- workspaceId: D,
149
- projectId: k,
150
- tenantId: j,
151
- setOrganization: N,
152
- setWorkspace: F,
153
- setProject: I,
154
- setTenant: L,
155
- setContext: R,
156
- clearContext: z,
157
- urlSyncEnabled: C
181
+ }, [T]), q = h(() => ({
182
+ organizationId: O,
183
+ workspaceId: A,
184
+ projectId: M,
185
+ tenantId: P,
186
+ setOrganization: B,
187
+ setWorkspace: H,
188
+ setProject: U,
189
+ setTenant: W,
190
+ setContext: G,
191
+ clearContext: K,
192
+ urlSyncEnabled: E
158
193
  }), [
159
- T,
160
- D,
161
- k,
162
- j,
163
- N,
164
- F,
165
- I,
166
- L,
167
- R,
168
- z,
169
- C
194
+ O,
195
+ A,
196
+ M,
197
+ P,
198
+ B,
199
+ H,
200
+ U,
201
+ W,
202
+ G,
203
+ K,
204
+ E
170
205
  ]);
171
- return /* @__PURE__ */ _(v.Provider, {
172
- value: B,
206
+ return /* @__PURE__ */ v(y.Provider, {
207
+ value: q,
173
208
  children: u
174
209
  });
175
210
  }
176
- function x() {
177
- let e = f(v);
211
+ function T() {
212
+ let e = f(y);
178
213
  if (!e) throw Error("useActiveContext must be used within an ActiveContextProvider");
179
214
  return e;
180
215
  }
181
216
  //#endregion
182
- export { b as ActiveContextProvider, x as useActiveContext };
217
+ export { w as ActiveContextProvider, T as useActiveContext };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fe-libs",
3
- "version": "2026.723.5",
3
+ "version": "2026.725.1",
4
4
  "description": "Burdenoff frontend primitives and domain libraries",
5
5
  "type": "module",
6
6
  "imports": {