@memobit/libs 3.11.3 → 3.12.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.
@@ -2,34 +2,35 @@ import './QuickOptionUpdate.css';
2
2
  import { Modal as x } from "../Modal/Modal2.js";
3
3
  import { Radio as C } from "../Radio/Radio2.js";
4
4
  /* empty css */
5
- import { useEffect as S, useState as o } from "react";
6
- import { jsx as r, jsxs as b } from "react/jsx-runtime";
7
- var O = ({ isOpen: p = !1, list: c, title: f, onClose: t, onSave: u, icon: h, value: s }) => {
8
- const [a, l] = o(s), [i, d] = o(!1), [m, n] = o("");
5
+ import { useEffect as S, useState as n } from "react";
6
+ import { jsx as a, jsxs as b } from "react/jsx-runtime";
7
+ import { logger as q } from "@memobit/core";
8
+ var U = ({ isOpen: m = !1, list: c, title: f, onClose: t, onSave: u, icon: v, value: i }) => {
9
+ const [r, l] = n(i), [s, d] = n(!1), [p, o] = n("");
9
10
  S(() => {
10
- l(s);
11
- }, [s]);
12
- const v = async () => {
13
- if (!a) {
14
- n("Please select a value");
11
+ l(i);
12
+ }, [i]);
13
+ const g = async () => {
14
+ if (!r) {
15
+ o("Please select a value");
15
16
  return;
16
17
  }
17
- d(!0), n("");
18
+ d(!0), o("");
18
19
  try {
19
- await u(a);
20
+ await u(r);
20
21
  } catch (e) {
21
- n(e instanceof Error ? e.message : "Failed to save");
22
+ o(e instanceof Error ? e.message : "Failed to save");
22
23
  } finally {
23
24
  d(!1);
24
25
  }
25
- }, g = (e) => {
26
- typeof e == "string" || typeof e == "number" ? l(e) : console.error("Unsupported type used.");
26
+ }, h = (e) => {
27
+ typeof e == "string" || typeof e == "number" ? l(e) : q.error("QuickOptionUpdate received an unsupported value type", void 0, { type: typeof e });
27
28
  };
28
- return /* @__PURE__ */ r("div", {
29
+ return /* @__PURE__ */ a("div", {
29
30
  className: "quick-set",
30
31
  children: /* @__PURE__ */ b(x, {
31
- isOpen: p,
32
- titleIcon: h,
32
+ isOpen: m,
33
+ titleIcon: v,
33
34
  title: f,
34
35
  size: "small",
35
36
  onClose: t,
@@ -37,31 +38,31 @@ var O = ({ isOpen: p = !1, list: c, title: f, onClose: t, onSave: u, icon: h, va
37
38
  secondary: {
38
39
  text: "Cancel",
39
40
  variant: "default",
40
- disabled: i,
41
+ disabled: s,
41
42
  onClick: t
42
43
  },
43
44
  primary: {
44
- text: i ? "Saving..." : "Save",
45
+ text: s ? "Saving..." : "Save",
45
46
  variant: "success",
46
- disabled: i || !a,
47
- onClick: v
47
+ disabled: s || !r,
48
+ onClick: g
48
49
  },
49
- children: [/* @__PURE__ */ r("div", {
50
+ children: [/* @__PURE__ */ a("div", {
50
51
  className: "quick-set-list",
51
- children: c && c.map(({ key: e, label: k }) => /* @__PURE__ */ r(C, {
52
+ children: c && c.map(({ key: e, label: k }) => /* @__PURE__ */ a(C, {
52
53
  name: "ownership",
53
54
  label: k,
54
- checked: a === e,
55
+ checked: r === e,
55
56
  value: e,
56
- onChange: (y) => g(y)
57
+ onChange: (y) => h(y)
57
58
  }, `quick-update-ownership-${e}`))
58
- }), m && /* @__PURE__ */ r("div", {
59
+ }), p && /* @__PURE__ */ a("div", {
59
60
  className: "error-message",
60
- children: m
61
+ children: p
61
62
  })]
62
63
  })
63
64
  });
64
65
  };
65
66
  export {
66
- O as QuickOptionUpdate
67
+ U as QuickOptionUpdate
67
68
  };
@@ -1,111 +1,108 @@
1
- import { HttpMethod as s, buildRequestHeaders as w } from "../../helpers/Http.js";
2
- import { AuthContext as A } from "./AuthContext.context.js";
3
- import { useCallback as i, useEffect as U, useState as d } from "react";
4
- import { jsx as j } from "react/jsx-runtime";
5
- function C({ children: h, config: a }) {
6
- const [c, l] = d(null), [f, o] = d(!0);
7
- U(() => {
1
+ import { HttpMethod as o, buildRequestHeaders as A } from "../../helpers/Http.js";
2
+ import { AuthContext as U } from "./AuthContext.context.js";
3
+ import { useCallback as i, useEffect as j, useState as c } from "react";
4
+ import { jsx as B } from "react/jsx-runtime";
5
+ import { logger as h } from "@memobit/core";
6
+ function C({ children: f, config: a }) {
7
+ const [d, u] = c(null), [p, s] = c(!0);
8
+ j(() => {
8
9
  (async () => {
9
10
  try {
10
11
  const t = await fetch(`${a.apiBaseUrl}/auth/verify`, {
11
- method: s.Get,
12
+ method: o.Get,
12
13
  credentials: "include",
13
14
  headers: { "Content-Type": "application/json" }
14
15
  });
15
16
  if (t.ok) {
16
- const e = await t.json();
17
- l({
18
- id: e.user.id,
19
- username: e.user.username,
20
- createdAt: new Date(e.user.createdAt)
17
+ const r = await t.json();
18
+ u({
19
+ id: r.user.id,
20
+ username: r.user.username,
21
+ createdAt: new Date(r.user.createdAt)
21
22
  });
22
23
  }
23
24
  } catch (t) {
24
- console.error("Failed to restore auth state:", t);
25
+ h.warn("Auth check could not reach the server", { error: String(t) });
25
26
  } finally {
26
- o(!1);
27
+ s(!1);
27
28
  }
28
29
  })();
29
30
  }, [a.apiBaseUrl]);
30
- const n = i((r) => {
31
- r.user && l({
32
- id: r.user.id,
33
- username: r.user.username,
34
- createdAt: new Date(r.user.createdAt)
31
+ const n = i((e) => {
32
+ e.user && u({
33
+ id: e.user.id,
34
+ username: e.user.username,
35
+ createdAt: new Date(e.user.createdAt)
35
36
  });
36
- }, []), p = i(async (r) => {
37
- o(!0);
37
+ }, []), m = i(async (e) => {
38
+ s(!0);
38
39
  try {
39
40
  const t = await fetch(`${a.apiBaseUrl}/auth/login`, {
40
- method: s.Post,
41
+ method: o.Post,
41
42
  credentials: "include",
42
43
  headers: { "Content-Type": "application/json" },
43
44
  body: JSON.stringify({
44
- username: r.username,
45
- password: r.password,
46
- rememberMe: r.rememberMe
45
+ username: e.username,
46
+ password: e.password,
47
+ rememberMe: e.rememberMe
47
48
  })
48
49
  });
49
50
  if (!t.ok) {
50
- const u = await t.json();
51
- throw new Error(u.error || "Login failed");
51
+ const l = await t.json();
52
+ throw new Error(l.error || "Login failed");
52
53
  }
53
- const e = await t.json();
54
- return e.mfaRequired ? {
54
+ const r = await t.json();
55
+ return r.mfaRequired ? {
55
56
  mfaRequired: !0,
56
- method: e.method
57
- } : (n(e), { mfaRequired: !1 });
58
- } catch (t) {
59
- throw console.error("Login failed:", t), t;
57
+ method: r.method
58
+ } : (n(r), { mfaRequired: !1 });
60
59
  } finally {
61
- o(!1);
60
+ s(!1);
62
61
  }
63
- }, [a.apiBaseUrl, n]), m = i(async (r, t) => {
64
- o(!0);
62
+ }, [a.apiBaseUrl, n]), y = i(async (e, t) => {
63
+ s(!0);
65
64
  try {
66
- const e = await fetch(`${a.apiBaseUrl}/auth/verifyMfa`, {
67
- method: s.Post,
65
+ const r = await fetch(`${a.apiBaseUrl}/auth/verifyMfa`, {
66
+ method: o.Post,
68
67
  credentials: "include",
69
68
  headers: { "Content-Type": "application/json" },
70
69
  body: JSON.stringify({
71
- code: r,
70
+ code: e,
72
71
  trustDevice: t
73
72
  })
74
73
  });
75
- if (!e.ok) {
76
- const u = await e.json();
77
- throw new Error(u.error || "Verification failed");
74
+ if (!r.ok) {
75
+ const l = await r.json();
76
+ throw new Error(l.error || "Verification failed");
78
77
  }
79
- n(await e.json());
80
- } catch (e) {
81
- throw console.error("MFA verification failed:", e), e;
78
+ n(await r.json());
82
79
  } finally {
83
- o(!1);
80
+ s(!1);
84
81
  }
85
- }, [a.apiBaseUrl, n]), y = i(async () => {
82
+ }, [a.apiBaseUrl, n]), w = i(async () => {
86
83
  try {
87
84
  await fetch(`${a.apiBaseUrl}/auth/logout`, {
88
- method: s.Post,
85
+ method: o.Post,
89
86
  credentials: "include",
90
- headers: w(s.Post)
87
+ headers: A(o.Post)
91
88
  });
92
- } catch (r) {
93
- console.error("Logout error:", r);
89
+ } catch (e) {
90
+ h.warn("Logout request failed", { error: String(e) });
94
91
  } finally {
95
- l(null);
92
+ u(null);
96
93
  }
97
94
  }, [a.apiBaseUrl]);
98
- return /* @__PURE__ */ j(A.Provider, {
95
+ return /* @__PURE__ */ B(U.Provider, {
99
96
  value: {
100
- user: c,
101
- isAuthenticated: !!c,
102
- isLoading: f,
97
+ user: d,
98
+ isAuthenticated: !!d,
99
+ isLoading: p,
103
100
  config: a,
104
- login: p,
105
- verifyMfa: m,
106
- logout: y
101
+ login: m,
102
+ verifyMfa: y,
103
+ logout: w
107
104
  },
108
- children: h
105
+ children: f
109
106
  });
110
107
  }
111
108
  export {
@@ -1,34 +1,41 @@
1
- var g = class {
1
+ import { logger as g } from "@memobit/core";
2
+ var n = class {
2
3
  static getData(e, t) {
3
4
  try {
4
- const a = localStorage.getItem(e);
5
- if (a) {
6
- const r = JSON.parse(a), o = { ...t.pages };
7
- if (r.pages && typeof r.pages == "object") for (const s of Object.keys(r.pages)) {
8
- const c = t.pages[s], n = r.pages[s];
5
+ const r = localStorage.getItem(e);
6
+ if (r) {
7
+ const a = JSON.parse(r), o = { ...t.pages };
8
+ if (a.pages && typeof a.pages == "object") for (const s of Object.keys(a.pages)) {
9
+ const c = t.pages[s], i = a.pages[s];
9
10
  c && typeof c == "object" ? o[s] = {
10
11
  ...c,
11
- ...n
12
- } : o[s] = n;
12
+ ...i
13
+ } : o[s] = i;
13
14
  }
14
15
  return {
15
16
  pages: o,
16
17
  theme: {
17
18
  ...t.theme,
18
- ...r.theme
19
+ ...a.theme
19
20
  }
20
21
  };
21
22
  }
22
- } catch (a) {
23
- console.warn(`Failed to load app persistence data for ${e}:`, a);
23
+ } catch (r) {
24
+ g.debug("Failed to load app persistence data", {
25
+ appId: e,
26
+ error: String(r)
27
+ });
24
28
  }
25
29
  return t;
26
30
  }
27
31
  static saveData(e, t) {
28
32
  try {
29
33
  localStorage.setItem(e, JSON.stringify(t));
30
- } catch (a) {
31
- console.warn(`Failed to save app persistence data for ${e}:`, a);
34
+ } catch (r) {
35
+ g.debug("Failed to save app persistence data", {
36
+ appId: e,
37
+ error: String(r)
38
+ });
32
39
  }
33
40
  }
34
41
  static load(e, t) {
@@ -41,10 +48,13 @@ var g = class {
41
48
  try {
42
49
  localStorage.removeItem(e);
43
50
  } catch (t) {
44
- console.warn(`Failed to clear app persistence data for ${e}:`, t);
51
+ g.debug("Failed to clear app persistence data", {
52
+ appId: e,
53
+ error: String(t)
54
+ });
45
55
  }
46
56
  }
47
57
  };
48
58
  export {
49
- g as AppPersistenceStorage
59
+ n as AppPersistenceStorage
50
60
  };
@@ -1,4 +1,5 @@
1
- var l = {
1
+ import { logger as p } from "@memobit/core";
2
+ var c = {
2
3
  Continue: 100,
3
4
  SwitchingProtocols: 101,
4
5
  Ok: 200,
@@ -32,71 +33,98 @@ var l = {
32
33
  BadGateway: 502,
33
34
  ServiceUnavailable: 503,
34
35
  GatewayTimeout: 504
35
- }, n = {
36
+ }, s = {
36
37
  Get: "GET",
37
38
  Post: "POST",
38
39
  Put: "PUT",
39
40
  Patch: "PATCH",
40
41
  Delete: "DELETE"
41
- }, w = (e) => e >= 200 && e < 300, C = (e) => e >= 400 && e < 500, E = (e) => e >= 500 && e < 600, f = "csrf_token", h = "X-CSRF-Token", v = () => {
42
- const e = document.cookie.match(new RegExp(`(?:^|;\\s*)${f}=([^;]+)`));
42
+ }, A = (e) => e >= 200 && e < 300, R = (e) => e >= 400 && e < 500, U = (e) => e >= 500 && e < 600, y = "csrf_token", S = "X-CSRF-Token", T = () => {
43
+ const e = document.cookie.match(new RegExp(`(?:^|;\\s*)${y}=([^;]+)`));
43
44
  return e ? decodeURIComponent(e[1]) : null;
44
- }, m = (e, r = !0) => {
45
- const s = r ? { "Content-Type": "application/json" } : {};
46
- if (e !== n.Get) {
47
- const i = v();
48
- i && (s[h] = i);
45
+ }, m = (e, t = !0) => {
46
+ const n = t ? { "Content-Type": "application/json" } : {};
47
+ if (e !== s.Get) {
48
+ const u = T();
49
+ u && (n[S] = u);
49
50
  }
50
- return s;
51
- }, y = class extends Error {
52
- constructor(e, r) {
53
- super(e), this.name = "ApiError", this.status = r;
51
+ return n;
52
+ }, v = class extends Error {
53
+ constructor(e, t) {
54
+ super(e), this.name = "ApiError", this.status = t;
54
55
  }
55
- }, T = async (e) => {
56
+ }, P = async (e) => {
56
57
  try {
57
- const r = await e.json();
58
- if (r && typeof r == "object") {
59
- if ("error" in r && typeof r.error == "string") return r.error;
60
- if ("message" in r && typeof r.message == "string") return r.message;
58
+ const t = await e.json();
59
+ if (t && typeof t == "object") {
60
+ if ("error" in t && typeof t.error == "string") return t.error;
61
+ if ("message" in t && typeof t.message == "string") return t.message;
61
62
  }
62
63
  } catch {
63
64
  }
64
65
  return `Request failed (${e.status}${e.statusText ? ` ${e.statusText}` : ""})`;
65
- }, P = ({ baseUrl: e, loginPath: r = "/login" }) => {
66
- let s = !1;
67
- const i = (t) => `${e.replace(/\/$/, "")}/${t.replace(/^\//, "")}`, c = async (t, o, u, p = !0) => {
68
- const a = await fetch(i(t), {
66
+ }, w = (e) => e instanceof DOMException && e.name === "AbortError", b = (e, t, n) => {
67
+ t instanceof v || w(t) || p.error(e, t, n);
68
+ }, g = /* @__PURE__ */ new Set([
69
+ c.BadGateway,
70
+ c.ServiceUnavailable,
71
+ c.GatewayTimeout
72
+ ]), G = ({ baseUrl: e, loginPath: t = "/login" }) => {
73
+ let n = !1;
74
+ const u = (r) => `${e.replace(/\/$/, "")}/${r.replace(/^\//, "")}`, d = async (r, o, l, E = !0) => {
75
+ const h = {
69
76
  method: o,
70
- headers: m(o, p),
71
- credentials: "include",
72
- body: u
73
- });
74
- if (a.status === l.Unauthorized && !window.location.pathname.startsWith(r))
75
- return s || (s = !0, window.location.href = `${r}?session_expired=true`), new Promise(() => {
77
+ path: r.split("?")[0]
78
+ };
79
+ let a;
80
+ try {
81
+ a = await fetch(u(r), {
82
+ method: o,
83
+ headers: m(o, E),
84
+ credentials: "include",
85
+ body: l
76
86
  });
77
- if (!a.ok) throw new y(await T(a), a.status);
78
- if (a.status !== l.NoContent)
79
- return await a.json();
80
- }, d = (t, o, u) => c(t, o, u === void 0 ? void 0 : JSON.stringify(u));
87
+ } catch (i) {
88
+ throw w(i) ? i : (p.warn("API request could not reach the server", h), new v("Could not reach the server", 0));
89
+ }
90
+ if (a.status === c.Unauthorized && !window.location.pathname.startsWith(t))
91
+ return n || (n = !0, window.location.href = `${t}?session_expired=true`), new Promise(() => {
92
+ });
93
+ if (!a.ok)
94
+ throw g.has(a.status) && p.warn("API gateway failure", {
95
+ ...h,
96
+ status: a.status
97
+ }), new v(await P(a), a.status);
98
+ if (a.status !== c.NoContent)
99
+ try {
100
+ return await a.json();
101
+ } catch (i) {
102
+ throw p.error("API response was not valid JSON", i, {
103
+ ...h,
104
+ status: a.status
105
+ }), i;
106
+ }
107
+ }, f = (r, o, l) => d(r, o, l === void 0 ? void 0 : JSON.stringify(l));
81
108
  return {
82
- get: (t) => c(t, n.Get),
83
- post: (t, o) => d(t, n.Post, o),
84
- put: (t, o) => d(t, n.Put, o),
85
- patch: (t, o) => d(t, n.Patch, o),
86
- delete: (t) => c(t, n.Delete),
87
- upload: (t, o) => c(t, n.Post, o, !1)
109
+ get: (r) => d(r, s.Get),
110
+ post: (r, o) => f(r, s.Post, o),
111
+ put: (r, o) => f(r, s.Put, o),
112
+ patch: (r, o) => f(r, s.Patch, o),
113
+ delete: (r) => d(r, s.Delete),
114
+ upload: (r, o) => d(r, s.Post, o, !1)
88
115
  };
89
116
  };
90
117
  export {
91
- y as ApiError,
92
- h as CSRF_HEADER,
93
- n as HttpMethod,
94
- l as HttpStatus,
118
+ v as ApiError,
119
+ S as CSRF_HEADER,
120
+ s as HttpMethod,
121
+ c as HttpStatus,
95
122
  m as buildRequestHeaders,
96
- P as createApiClient,
97
- v as getCsrfToken,
98
- C as isClientErrorStatus,
99
- E as isServerErrorStatus,
100
- w as isSuccessStatus,
101
- T as readErrorMessage
123
+ G as createApiClient,
124
+ T as getCsrfToken,
125
+ R as isClientErrorStatus,
126
+ U as isServerErrorStatus,
127
+ A as isSuccessStatus,
128
+ b as logUnexpectedError,
129
+ P as readErrorMessage
102
130
  };
@@ -23,7 +23,7 @@ var r = (i) => {
23
23
  const o = {
24
24
  ...i,
25
25
  lib: d,
26
- libBuildNumber: 512,
26
+ libBuildNumber: 515,
27
27
  libCommit: n,
28
28
  libBuildDate: t
29
29
  };
package/dist/http.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare interface ApiClientConfig {
12
12
  loginPath?: string;
13
13
  }
14
14
 
15
+ /** A failed API request. `status` is the HTTP status, or 0 when the server could not be reached. */
15
16
  export declare class ApiError extends Error {
16
17
  readonly status: number;
17
18
  constructor(message: string, status: number);
@@ -24,6 +25,9 @@ export declare const buildRequestHeaders: (method: HttpMethod, json?: boolean) =
24
25
  * header on mutating requests, surfaces the server's `error` message, and on 401 navigates
25
26
  * to the login page. The 401 path returns a promise that never settles so callers don't
26
27
  * flash an error toast while the browser is already leaving the page.
28
+ *
29
+ * It reports unreachable-server, gateway and invalid-JSON failures to the hub, so callers
30
+ * only show a toast for API errors and don't log them again.
27
31
  */
28
32
  export declare const createApiClient: ({ baseUrl, loginPath }: ApiClientConfig) => ApiClient;
29
33
 
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ import { Context } from 'react';
4
4
  import { CSSProperties } from 'react';
5
5
  import { default as default_2 } from 'react';
6
6
  import { ErrorInfo } from 'react';
7
+ import { ErrorReportContext } from '@memobit/core';
7
8
  import { FC } from 'react';
8
9
  import { FocusEvent as FocusEvent_2 } from 'react';
9
10
  import { ForwardRefExoticComponent } from 'react';
@@ -125,6 +126,7 @@ export declare interface ApiClientConfig {
125
126
  loginPath?: string;
126
127
  }
127
128
 
129
+ /** A failed API request. `status` is the HTTP status, or 0 when the server could not be reached. */
128
130
  export declare class ApiError extends Error {
129
131
  readonly status: number;
130
132
  constructor(message: string, status: number);
@@ -1027,6 +1029,9 @@ declare interface CountryWithFlagProps {
1027
1029
  * header on mutating requests, surfaces the server's `error` message, and on 401 navigates
1028
1030
  * to the login page. The 401 path returns a promise that never settles so callers don't
1029
1031
  * flash an error toast while the browser is already leaving the page.
1032
+ *
1033
+ * It reports unreachable-server, gateway and invalid-JSON failures to the hub, so callers
1034
+ * only show a toast for API errors and don't log them again.
1030
1035
  */
1031
1036
  export declare const createApiClient: ({ baseUrl, loginPath }: ApiClientConfig) => ApiClient;
1032
1037
 
@@ -2387,6 +2392,13 @@ export declare interface LoginResponse {
2387
2392
  method?: MfaMethod;
2388
2393
  }
2389
2394
 
2395
+ /**
2396
+ * For the catch around an API call: reports `error` unless it is an `ApiError` (the client and
2397
+ * the backend already report those that matter) or an aborted request. What is left is a bug in
2398
+ * the code around the call, e.g. mapping the response.
2399
+ */
2400
+ export declare const logUnexpectedError: (message: string, error: unknown, context?: ErrorReportContext) => void;
2401
+
2390
2402
  export declare const matchStringsByLogicalOperator: (searchItems: string[], targetString: string, operator: LogicalOperator) => boolean;
2391
2403
 
2392
2404
  export declare const MenuHamburger: FC<MenuHamburgerProps>;
package/dist/index.js CHANGED
@@ -135,25 +135,25 @@ import { Transition as wi } from "./components/Transition/Transition2.js";
135
135
  import { Tree as Ui } from "./components/Tree/Tree2.js";
136
136
  import { VirtualList as Wi } from "./components/VirtualList/VirtualList2.js";
137
137
  import { WHtR as zi } from "./components/WHtR/WHtR2.js";
138
- import { ApiError as qi, CSRF_HEADER as ji, HttpMethod as Ji, HttpStatus as Ki, buildRequestHeaders as Xi, createApiClient as Yi, getCsrfToken as Zi, isClientErrorStatus as $i, isServerErrorStatus as re, isSuccessStatus as oe, readErrorMessage as te } from "./helpers/Http.js";
139
- import { AuthContext as ie } from "./contexts/AuthContext/AuthContext.context.js";
140
- import { AuthProvider as pe } from "./contexts/AuthContext/AuthContext.js";
141
- import { useAuth as ae } from "./hooks/useAuth/useAuth.js";
142
- import { ChangePasswordModal as le } from "./components/Auth/ChangePasswordModal/ChangePasswordModal2.js";
143
- import { Login as ue } from "./components/Auth/Login/Login2.js";
144
- import { useAccountMenu as ce } from "./hooks/useAccountMenu.js";
145
- import { AppPersistenceStorage as Te } from "./helpers/AppPersistenceStorage.js";
146
- import { useAppPersistence as Ie } from "./hooks/useAppPersistence.js";
147
- import { chartColors as Ce, chartTooltipStyle as De } from "./helpers/Charts.js";
148
- import { formatBigNumber as Ae, formatBytes as Me, formatMoney as Be } from "./helpers/Format.js";
149
- import { highlightText as Ee } from "./helpers/Highlight.js";
150
- import { DATA_FILES_PATH as ye, createImagePaths as Le } from "./helpers/Images.js";
151
- import { matchStringsByLogicalOperator as be } from "./helpers/LogicalOperators.js";
152
- import { shortenText as xe, slugify as He, truncateText as Fe } from "./helpers/Strings.js";
153
- import { extractDomainFromUrl as we, stripQueryString as Oe, stripTrackingParams as Ue } from "./helpers/Urls.js";
154
- import { LIB_BUILD_DATE as We, LIB_BUILD_ID as Qe, LIB_BUILD_NUMBER as ze, LIB_COMMIT as Ge, LIB_VERSION as qe } from "./version.js";
155
- import { initVersionInfo as Je } from "./helpers/VersionInfo.js";
156
- import { validateVin as Xe } from "./validators/Vin.js";
138
+ import { ApiError as qi, CSRF_HEADER as ji, HttpMethod as Ji, HttpStatus as Ki, buildRequestHeaders as Xi, createApiClient as Yi, getCsrfToken as Zi, isClientErrorStatus as $i, isServerErrorStatus as re, isSuccessStatus as oe, logUnexpectedError as te, readErrorMessage as me } from "./helpers/Http.js";
139
+ import { AuthContext as ee } from "./contexts/AuthContext/AuthContext.context.js";
140
+ import { AuthProvider as fe } from "./contexts/AuthContext/AuthContext.js";
141
+ import { useAuth as ne } from "./hooks/useAuth/useAuth.js";
142
+ import { ChangePasswordModal as se } from "./components/Auth/ChangePasswordModal/ChangePasswordModal2.js";
143
+ import { Login as de } from "./components/Auth/Login/Login2.js";
144
+ import { useAccountMenu as ge } from "./hooks/useAccountMenu.js";
145
+ import { AppPersistenceStorage as Se } from "./helpers/AppPersistenceStorage.js";
146
+ import { useAppPersistence as Pe } from "./hooks/useAppPersistence.js";
147
+ import { chartColors as De, chartTooltipStyle as he } from "./helpers/Charts.js";
148
+ import { formatBigNumber as Me, formatBytes as Be, formatMoney as ke } from "./helpers/Format.js";
149
+ import { highlightText as Re } from "./helpers/Highlight.js";
150
+ import { DATA_FILES_PATH as Le, createImagePaths as _e } from "./helpers/Images.js";
151
+ import { matchStringsByLogicalOperator as ve } from "./helpers/LogicalOperators.js";
152
+ import { shortenText as He, slugify as Fe, truncateText as Ne } from "./helpers/Strings.js";
153
+ import { extractDomainFromUrl as Oe, stripQueryString as Ue, stripTrackingParams as Ve } from "./helpers/Urls.js";
154
+ import { LIB_BUILD_DATE as Qe, LIB_BUILD_ID as ze, LIB_BUILD_NUMBER as Ge, LIB_COMMIT as qe, LIB_VERSION as je } from "./version.js";
155
+ import { initVersionInfo as Ke } from "./helpers/VersionInfo.js";
156
+ import { validateVin as Ye } from "./validators/Vin.js";
157
157
  export {
158
158
  N as ADULT_RANGES,
159
159
  Y as APP_DATE_FORMAT,
@@ -164,10 +164,10 @@ export {
164
164
  A as AngleSlider,
165
165
  qi as ApiError,
166
166
  E as AppHeader,
167
- Te as AppPersistenceStorage,
168
- ie as AuthContext,
169
- ue as AuthLogin,
170
- pe as AuthProvider,
167
+ Se as AppPersistenceStorage,
168
+ ee as AuthContext,
169
+ de as AuthLogin,
170
+ fe as AuthProvider,
171
171
  y as AvatarInitials,
172
172
  G as BMI,
173
173
  _ as Badge,
@@ -180,7 +180,7 @@ export {
180
180
  Cr as Calendar,
181
181
  hr as CalendarHeatmap,
182
182
  Mr as Card,
183
- le as ChangePasswordModal,
183
+ se as ChangePasswordModal,
184
184
  kr as Checkbox,
185
185
  Rr as Chip,
186
186
  Et as Col,
@@ -195,7 +195,7 @@ export {
195
195
  yo as ControlPanelProvider,
196
196
  _o as CopyButton,
197
197
  Ho as CountryWithFlag,
198
- ye as DATA_FILES_PATH,
198
+ Le as DATA_FILES_PATH,
199
199
  Yo as DataView,
200
200
  eo as DatePicker,
201
201
  $o as DateRangePicker,
@@ -233,11 +233,11 @@ export {
233
233
  $t as InputTime,
234
234
  om as InputUrl,
235
235
  mm as JourneyWizard,
236
- We as LIB_BUILD_DATE,
237
- Qe as LIB_BUILD_ID,
238
- ze as LIB_BUILD_NUMBER,
239
- Ge as LIB_COMMIT,
240
- qe as LIB_VERSION,
236
+ Qe as LIB_BUILD_DATE,
237
+ ze as LIB_BUILD_ID,
238
+ Ge as LIB_BUILD_NUMBER,
239
+ qe as LIB_COMMIT,
240
+ je as LIB_VERSION,
241
241
  em as List,
242
242
  At as Loading,
243
243
  fm as MenuHamburger,
@@ -303,23 +303,23 @@ export {
303
303
  Xi as buildRequestHeaders,
304
304
  O as calculateBMI,
305
305
  Qo as calculateTimelineMarkers,
306
- Ce as chartColors,
307
- De as chartTooltipStyle,
306
+ De as chartColors,
307
+ he as chartTooltipStyle,
308
308
  Pm as clamp,
309
309
  Yi as createApiClient,
310
- Le as createImagePaths,
310
+ _e as createImagePaths,
311
311
  Um as ensureHtml,
312
- we as extractDomainFromUrl,
312
+ Oe as extractDomainFromUrl,
313
313
  fo as foldDiacritics,
314
314
  Cm as format2Digits,
315
315
  or as formatAppDate,
316
316
  tr as formatAppDateTime,
317
- Ae as formatBigNumber,
318
- Me as formatBytes,
317
+ Me as formatBigNumber,
318
+ Be as formatBytes,
319
319
  mr as formatDate,
320
320
  ir as formatDateLocale,
321
321
  er as formatDuration,
322
- Be as formatMoney,
322
+ ke as formatMoney,
323
323
  pr as formatRelativeDuration,
324
324
  fr as formatRelativeTime,
325
325
  ar as formatSecondsToMediaTime,
@@ -337,10 +337,10 @@ export {
337
337
  No as getResultsCount,
338
338
  Ci as getThemeConfig,
339
339
  ur as getTodayDateString,
340
- Ee as highlightText,
340
+ Re as highlightText,
341
341
  Vm as htmlToMarkdown,
342
342
  Wm as htmlToPlainText,
343
- Je as initVersionInfo,
343
+ Ke as initVersionInfo,
344
344
  dr as isAfter,
345
345
  cr as isBefore,
346
346
  $i as isClientErrorStatus,
@@ -350,17 +350,18 @@ export {
350
350
  oe as isSuccessStatus,
351
351
  Sr as isToday,
352
352
  Ir as isWeekend,
353
- be as matchStringsByLogicalOperator,
354
- te as readErrorMessage,
355
- xe as shortenText,
356
- He as slugify,
353
+ te as logUnexpectedError,
354
+ ve as matchStringsByLogicalOperator,
355
+ me as readErrorMessage,
356
+ He as shortenText,
357
+ Fe as slugify,
357
358
  Qm as splitHtmlIntoSteps,
358
- Oe as stripQueryString,
359
- Ue as stripTrackingParams,
360
- Fe as truncateText,
361
- ce as useAccountMenu,
362
- Ie as useAppPersistence,
363
- ae as useAuth,
359
+ Ue as stripQueryString,
360
+ Ve as stripTrackingParams,
361
+ Ne as truncateText,
362
+ ge as useAccountMenu,
363
+ Pe as useAppPersistence,
364
+ ne as useAuth,
364
365
  e as useBodyScrollLock,
365
366
  Eo as useBreakpoint,
366
367
  s as useComponentEffect,
@@ -372,5 +373,5 @@ export {
372
373
  n as useTheme,
373
374
  Zr as useToast,
374
375
  Ht as validateEmail,
375
- Xe as validateVin
376
+ Ye as validateVin
376
377
  };
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
- var I = "3.11.3", B = 512, L = "4616cb0", _ = "2026-10-16T19:10:24.770Z", r = "512";
1
+ var I = "3.12.0", B = 515, L = "3e853ab", _ = "2026-10-16T19:55:36.011Z", a = "515";
2
2
  export {
3
3
  _ as LIB_BUILD_DATE,
4
- r as LIB_BUILD_ID,
4
+ a as LIB_BUILD_ID,
5
5
  B as LIB_BUILD_NUMBER,
6
6
  L as LIB_COMMIT,
7
7
  I as LIB_VERSION
package/dist/version.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "3.11.3",
3
- "buildNumber": 512,
4
- "commit": "4616cb0",
5
- "buildDate": "2026-10-16T19:10:24.770Z"
2
+ "version": "3.12.0",
3
+ "buildNumber": 515,
4
+ "commit": "3e853ab",
5
+ "buildDate": "2026-10-16T19:55:36.011Z"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memobit/libs",
3
- "version": "3.11.3",
3
+ "version": "3.12.0",
4
4
  "description": "React component library powering the Memobit apps — 100+ components, helpers and hooks. Icons ship as @memobit/icons and themes as @memobit/themes. TypeScript-first, ESM-only, React 19.",
5
5
  "keywords": [
6
6
  "react",