important changes
This commit is contained in:
parent
e1f501fa48
commit
c75420a91c
1
dist/core.d.ts
vendored
1
dist/core.d.ts
vendored
@ -41,7 +41,6 @@ export type BiProviderProps = {
|
||||
permissionEnabled?: boolean;
|
||||
theme?: any;
|
||||
remoteUiEnabled?: boolean;
|
||||
remoteUiUrl?: string;
|
||||
remoteUiChakraProviderProps?: Record<string, any>;
|
||||
};
|
||||
|
||||
|
||||
523
dist/core.js
vendored
523
dist/core.js
vendored
@ -1,78 +1,79 @@
|
||||
import j from "axios";
|
||||
import { jsx as q, jsxs as M } from "react/jsx-runtime";
|
||||
import _ from "keycloak-js";
|
||||
import $, { createContext as V, useState as z, useRef as N, useCallback as X, useEffect as g, useMemo as x, useContext as ee } from "react";
|
||||
import { useQueryClient as te, useMutation as re, useQuery as f, QueryClient as ne, QueryClientProvider as oe } from "@tanstack/react-query";
|
||||
import { extendTheme as ie, withDefaultColorScheme as se, ChakraProvider as R, Spinner as ae, Badge as ue } from "@chakra-ui/react";
|
||||
import Q from "axios";
|
||||
import { jsx as Z, jsxs as A } from "react/jsx-runtime";
|
||||
import j from "keycloak-js";
|
||||
import _, { createContext as C, useState as X, useRef as L, useCallback as K, useEffect as z, useMemo as g, useContext as $ } from "react";
|
||||
import { useQueryClient as ee, useMutation as te, useQuery as f, QueryClient as re, QueryClientProvider as ne } from "@tanstack/react-query";
|
||||
import { createRoot as oe } from "react-dom/client";
|
||||
import { extendTheme as ie, withDefaultColorScheme as se, ChakraProvider as V, Spinner as ae, Badge as ue } from "@chakra-ui/react";
|
||||
import { Global as de } from "@emotion/react";
|
||||
let W = null, o = null, O = null, v = !1;
|
||||
const ce = V(null), le = ({ url: e, realm: t, clientId: r }) => (o || (o = new _({
|
||||
let W = null, o = null, Y = null, O = !1;
|
||||
const ce = C(null), le = ({ url: e, realm: r, clientId: t }) => (o || (o = new j({
|
||||
url: e,
|
||||
realm: t,
|
||||
clientId: r
|
||||
})), o), he = (e) => (W = e, W), Fe = () => v, I = () => !!(o != null && o.authenticated), w = () => (o == null ? void 0 : o.token) ?? null, D = async (e = 30) => o ? o.updateToken(e) : !1, G = (e) => o == null ? void 0 : o.logout(e), Ge = (e) => o == null ? void 0 : o.login(e), J = ({ config: e, initOptions: t = {} } = {}) => {
|
||||
const r = e ?? W;
|
||||
if (!(r != null && r.url) || !(r != null && r.realm) || !(r != null && r.clientId))
|
||||
realm: r,
|
||||
clientId: t
|
||||
})), o), he = (e) => (W = e, W), Se = () => O, N = () => !!(o != null && o.authenticated), x = () => (o == null ? void 0 : o.token) ?? null, D = async (e = 30) => o ? o.updateToken(e) : !1, R = (e) => o == null ? void 0 : o.logout(e), Je = (e) => o == null ? void 0 : o.login(e), I = ({ config: e, initOptions: r = {} } = {}) => {
|
||||
const t = e ?? W;
|
||||
if (!(t != null && t.url) || !(t != null && t.realm) || !(t != null && t.clientId))
|
||||
throw new Error("Keycloak config is required.");
|
||||
he(r);
|
||||
const n = le(r);
|
||||
return O || (O = n.init({
|
||||
he(t);
|
||||
const n = le(t);
|
||||
return Y || (Y = n.init({
|
||||
onLoad: "login-required",
|
||||
checkLoginIframe: !1,
|
||||
flow: "implicit",
|
||||
...t
|
||||
}).then((u) => (v = !0, u)).catch((u) => {
|
||||
throw v = !0, u;
|
||||
})), O;
|
||||
}, Se = ({
|
||||
...r
|
||||
}).then((d) => (O = !0, d)).catch((d) => {
|
||||
throw O = !0, d;
|
||||
})), Y;
|
||||
}, Fe = ({
|
||||
children: e,
|
||||
config: t,
|
||||
initOptions: r,
|
||||
config: r,
|
||||
initOptions: t,
|
||||
loading: n = null
|
||||
}) => {
|
||||
const [u, h] = z(!1), [d, s] = z(!1), [a, S] = z(null), p = N(!1), i = X(() => {
|
||||
o && (s(!!o.authenticated), S(o.token ?? null));
|
||||
const [d, l] = X(!1), [u, s] = X(!1), [a, F] = X(null), p = L(!1), i = K(() => {
|
||||
o && (s(!!o.authenticated), F(o.token ?? null));
|
||||
}, []);
|
||||
g(() => (p.current = !0, J({ config: t, initOptions: r }).then((c) => {
|
||||
p.current && (s(!!c), S((o == null ? void 0 : o.token) ?? null), h(!0));
|
||||
z(() => (p.current = !0, I({ config: r, initOptions: t }).then((h) => {
|
||||
p.current && (s(!!h), F((o == null ? void 0 : o.token) ?? null), l(!0));
|
||||
}).catch(() => {
|
||||
p.current && (s(!1), S(null), h(!0));
|
||||
p.current && (s(!1), F(null), l(!0));
|
||||
}), () => {
|
||||
p.current = !1;
|
||||
}), [t, r]);
|
||||
const l = X(() => o == null ? void 0 : o.login(), []), m = X((c) => o == null ? void 0 : o.logout(c), []), F = X(
|
||||
async (c = 30) => {
|
||||
}), [r, t]);
|
||||
const c = K(() => o == null ? void 0 : o.login(), []), m = K((h) => o == null ? void 0 : o.logout(h), []), S = K(
|
||||
async (h = 30) => {
|
||||
if (!o) return !1;
|
||||
const Z = await o.updateToken(c);
|
||||
return i(), Z;
|
||||
const E = await o.updateToken(h);
|
||||
return i(), E;
|
||||
},
|
||||
[i]
|
||||
), E = x(
|
||||
), q = g(
|
||||
() => ({
|
||||
initialized: u,
|
||||
authenticated: d,
|
||||
initialized: d,
|
||||
authenticated: u,
|
||||
token: a,
|
||||
login: l,
|
||||
login: c,
|
||||
logout: m,
|
||||
updateToken: F
|
||||
updateToken: S
|
||||
}),
|
||||
[u, d, a, l, m, F]
|
||||
[d, u, a, c, m, S]
|
||||
);
|
||||
return u ? /* @__PURE__ */ q(ce.Provider, { value: E, children: e }) : n;
|
||||
return d ? /* @__PURE__ */ Z(ce.Provider, { value: q, children: e }) : n;
|
||||
};
|
||||
let B = null;
|
||||
const pe = (e) => {
|
||||
const { api: t } = e, r = j.create({
|
||||
baseURL: t.baseUrl
|
||||
const { api: r } = e, t = Q.create({
|
||||
baseURL: r.baseUrl
|
||||
}), n = async () => {
|
||||
(!Fe() || !I()) && await J();
|
||||
}, u = !!e.keycloak, h = async (s) => {
|
||||
if (!u) return s;
|
||||
(!Se() || !N()) && await I();
|
||||
}, d = !!e.keycloak, l = async (s) => {
|
||||
if (!d) return s;
|
||||
await n();
|
||||
let a = w();
|
||||
let a = x();
|
||||
if (a) {
|
||||
try {
|
||||
await D(5), a = w();
|
||||
await D(5), a = x();
|
||||
} catch {
|
||||
}
|
||||
s.headers = {
|
||||
@ -81,271 +82,271 @@ const pe = (e) => {
|
||||
};
|
||||
}
|
||||
return s;
|
||||
}, d = async (s) => {
|
||||
var S;
|
||||
}, u = async (s) => {
|
||||
var F;
|
||||
const a = s.config;
|
||||
if (((S = s == null ? void 0 : s.response) == null ? void 0 : S.status) === 401 && !(a != null && a._retry)) {
|
||||
if (((F = s == null ? void 0 : s.response) == null ? void 0 : F.status) === 401 && !(a != null && a._retry)) {
|
||||
a._retry = !0;
|
||||
try {
|
||||
await D(30);
|
||||
const p = w();
|
||||
const p = x();
|
||||
return a.headers = {
|
||||
...a.headers,
|
||||
Authorization: `Bearer ${p}`
|
||||
}, r(a);
|
||||
}, t(a);
|
||||
} catch {
|
||||
G({ redirectUri: window.location.origin });
|
||||
R({ redirectUri: window.location.origin });
|
||||
}
|
||||
}
|
||||
return Promise.reject(s);
|
||||
};
|
||||
return r.interceptors.request.use(h), r.interceptors.response.use(
|
||||
return t.interceptors.request.use(l), t.interceptors.response.use(
|
||||
(s) => s,
|
||||
d
|
||||
u
|
||||
), {
|
||||
api: r
|
||||
api: t
|
||||
};
|
||||
}, me = (e) => (B = pe(e), B), Ee = () => {
|
||||
}, me = (e) => (B = pe(e), B), qe = () => {
|
||||
if (!B)
|
||||
throw new Error("api is not configured. Call configureApi(config) first.");
|
||||
return B.api;
|
||||
}, H = new Proxy(
|
||||
}, G = new Proxy(
|
||||
{},
|
||||
{
|
||||
get(e, t) {
|
||||
return Ee()[t];
|
||||
get(e, r) {
|
||||
return qe()[r];
|
||||
}
|
||||
}
|
||||
), qe = async (e) => (await H.get(e)).data;
|
||||
function P(e) {
|
||||
), Ee = async (e) => (await G.get(e)).data;
|
||||
function v(e) {
|
||||
return Array.isArray(e) ? e : [e];
|
||||
}
|
||||
function Ze(e) {
|
||||
return [...P(e), "list"];
|
||||
return [...v(e), "list"];
|
||||
}
|
||||
function C(e, t) {
|
||||
return [...P(e), t];
|
||||
function M(e, r) {
|
||||
return [...v(e), r];
|
||||
}
|
||||
function be(e, t) {
|
||||
if (!t) return e;
|
||||
const r = new URLSearchParams();
|
||||
Object.entries(t).forEach(([u, h]) => {
|
||||
h != null && h !== "" && r.append(u, h);
|
||||
function be(e, r) {
|
||||
if (!r) return e;
|
||||
const t = new URLSearchParams();
|
||||
Object.entries(r).forEach(([d, l]) => {
|
||||
l != null && l !== "" && t.append(d, l);
|
||||
});
|
||||
const n = r.toString();
|
||||
const n = t.toString();
|
||||
return n ? `${e}?${n}` : e;
|
||||
}
|
||||
function ye(e, t) {
|
||||
return typeof e == "function" ? e(t == null ? void 0 : t.id, t) : e;
|
||||
function ye(e, r) {
|
||||
return typeof e == "function" ? e(r == null ? void 0 : r.id, r) : e;
|
||||
}
|
||||
function Te(e = {}) {
|
||||
const { id: t, ...r } = e;
|
||||
return r;
|
||||
const { id: r, ...t } = e;
|
||||
return t;
|
||||
}
|
||||
function Ke(e, t) {
|
||||
return `${e.replace(/\/$/, "")}/${t}`;
|
||||
function Ke(e, r) {
|
||||
return `${e.replace(/\/$/, "")}/${r}`;
|
||||
}
|
||||
function Xe(e) {
|
||||
return `use${e.charAt(0).toUpperCase()}${e.slice(1)}`;
|
||||
}
|
||||
function Je({
|
||||
function He({
|
||||
key: e,
|
||||
url: t,
|
||||
actions: r = {},
|
||||
axiosInstance: n = H,
|
||||
fetcher: u = qe
|
||||
url: r,
|
||||
actions: t = {},
|
||||
axiosInstance: n = G,
|
||||
fetcher: d = Ee
|
||||
}) {
|
||||
const h = P(e), d = Ze(e);
|
||||
function s(i, l = {}) {
|
||||
const l = v(e), u = Ze(e);
|
||||
function s(i, c = {}) {
|
||||
return f({
|
||||
queryKey: i ? [...d, i] : d,
|
||||
queryFn: () => u(be(t, i)),
|
||||
...l
|
||||
queryKey: i ? [...u, i] : u,
|
||||
queryFn: () => d(be(r, i)),
|
||||
...c
|
||||
});
|
||||
}
|
||||
function a(i, l = {}) {
|
||||
function a(i, c = {}) {
|
||||
return f({
|
||||
queryKey: C(e, i),
|
||||
queryFn: () => u(Ke(t, i)),
|
||||
queryKey: M(e, i),
|
||||
queryFn: () => d(Ke(r, i)),
|
||||
enabled: !!i,
|
||||
...l
|
||||
...c
|
||||
});
|
||||
}
|
||||
function S(i, l = {}) {
|
||||
const m = te(), F = r[i];
|
||||
if (!F)
|
||||
function F(i, c = {}) {
|
||||
const m = ee(), S = t[i];
|
||||
if (!S)
|
||||
throw new Error(`Action "${i}" is not defined.`);
|
||||
return re({
|
||||
mutationKey: [...h, i],
|
||||
mutationFn: async (E = {}) => {
|
||||
const c = F.method || "post", Z = ye(F.url || t, E), b = F.body ? F.body(E) : F.sendRawPayload ? E : Te(E);
|
||||
return (c === "delete" ? await n.delete(
|
||||
Z,
|
||||
return te({
|
||||
mutationKey: [...l, i],
|
||||
mutationFn: async (q = {}) => {
|
||||
const h = S.method || "post", E = ye(S.url || r, q), b = S.body ? S.body(q) : S.sendRawPayload ? q : Te(q);
|
||||
return (h === "delete" ? await n.delete(
|
||||
E,
|
||||
b && Object.keys(b).length > 0 ? { data: b } : void 0
|
||||
) : await n[c](Z, b)).data;
|
||||
) : await n[h](E, b)).data;
|
||||
},
|
||||
onSuccess: (...E) => {
|
||||
onSuccess: (...q) => {
|
||||
var T;
|
||||
const [c, Z] = E;
|
||||
const [h, E] = q;
|
||||
m.invalidateQueries({
|
||||
queryKey: d
|
||||
queryKey: u
|
||||
});
|
||||
const b = (Z == null ? void 0 : Z.id) ?? (c == null ? void 0 : c.id);
|
||||
const b = (E == null ? void 0 : E.id) ?? (h == null ? void 0 : h.id);
|
||||
b && m.invalidateQueries({
|
||||
queryKey: C(e, b)
|
||||
queryKey: M(e, b)
|
||||
});
|
||||
const y = typeof F.invalidateKeys == "function" ? F.invalidateKeys(c, Z) : F.invalidateKeys;
|
||||
y == null || y.forEach((K) => {
|
||||
m.invalidateQueries({ queryKey: K });
|
||||
}), (T = l.onSuccess) == null || T.call(l, ...E);
|
||||
const y = typeof S.invalidateKeys == "function" ? S.invalidateKeys(h, E) : S.invalidateKeys;
|
||||
y == null || y.forEach((k) => {
|
||||
m.invalidateQueries({ queryKey: k });
|
||||
}), (T = c.onSuccess) == null || T.call(c, ...q);
|
||||
},
|
||||
...l
|
||||
...c
|
||||
});
|
||||
}
|
||||
const p = Object.keys(r).reduce((i, l) => (i[Xe(l)] = (m = {}) => S(l, m), i), {});
|
||||
const p = Object.keys(t).reduce((i, c) => (i[Xe(c)] = (m = {}) => F(c, m), i), {});
|
||||
return {
|
||||
key: h,
|
||||
listKey: d,
|
||||
key: l,
|
||||
listKey: u,
|
||||
useGet: s,
|
||||
useItem: a,
|
||||
useAction: S,
|
||||
useAction: F,
|
||||
...p
|
||||
};
|
||||
}
|
||||
const k = V(null), Y = "permissions", ze = (e) => (e == null ? void 0 : e.storageKey) || Y, ge = ({
|
||||
const J = C(null), w = "permissions", ze = (e) => (e == null ? void 0 : e.storageKey) || w, xe = ({
|
||||
user: e = null,
|
||||
children: t,
|
||||
config: r,
|
||||
loading: n = /* @__PURE__ */ q("div", { children: "Loading permissions..." }),
|
||||
errorFallback: u = /* @__PURE__ */ q("div", { children: "Error loading permissions" })
|
||||
children: r,
|
||||
config: t,
|
||||
loading: n = /* @__PURE__ */ Z("div", { children: "Loading permissions..." }),
|
||||
errorFallback: d = /* @__PURE__ */ Z("div", { children: "Error loading permissions" })
|
||||
}) => {
|
||||
const h = ze(r), [d, s] = z(
|
||||
() => we(h)
|
||||
), { data: a, isLoading: S, error: p } = fe(r), i = a ?? d;
|
||||
g(() => {
|
||||
a && (xe(h, a), s(a));
|
||||
}, [a, h]);
|
||||
const l = x(
|
||||
() => Be(i),
|
||||
const l = ze(t), [u, s] = X(
|
||||
() => ge(l)
|
||||
), { data: a, isLoading: F, error: p } = We(t), i = a ?? u;
|
||||
z(() => {
|
||||
a && (Be(l, a), s(a));
|
||||
}, [a, l]);
|
||||
const c = g(
|
||||
() => we(i),
|
||||
[i]
|
||||
), m = X(
|
||||
(c = "") => Ye(l, c),
|
||||
[l]
|
||||
), F = X((c = "") => !m(c), [m]), E = x(
|
||||
), m = K(
|
||||
(h = "") => Ye(c, h),
|
||||
[c]
|
||||
), S = K((h = "") => !m(h), [m]), q = g(
|
||||
() => ({
|
||||
user: e,
|
||||
can: m,
|
||||
cannot: F,
|
||||
cannot: S,
|
||||
permissions: i,
|
||||
isLoading: S,
|
||||
isLoading: F,
|
||||
error: p
|
||||
}),
|
||||
[e, m, F, i, S, p]
|
||||
[e, m, S, i, F, p]
|
||||
);
|
||||
return p && !i ? u : S && !i ? n : /* @__PURE__ */ q(k.Provider, { value: E, children: t });
|
||||
}, we = (e = Y) => {
|
||||
return p && !i ? d : F && !i ? n : /* @__PURE__ */ Z(J.Provider, { value: q, children: r });
|
||||
}, ge = (e = w) => {
|
||||
if (!(typeof window > "u"))
|
||||
try {
|
||||
const t = localStorage.getItem(e);
|
||||
return t ? JSON.parse(t) : void 0;
|
||||
const r = localStorage.getItem(e);
|
||||
return r ? JSON.parse(r) : void 0;
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
}, xe = (e = Y, t) => {
|
||||
}, Be = (e = w, r) => {
|
||||
if (!(typeof window > "u"))
|
||||
try {
|
||||
localStorage.setItem(e, JSON.stringify(t));
|
||||
localStorage.setItem(e, JSON.stringify(r));
|
||||
} catch {
|
||||
}
|
||||
}, He = (e = Y) => {
|
||||
}, ke = (e = w) => {
|
||||
if (!(typeof window > "u"))
|
||||
try {
|
||||
localStorage.removeItem(e);
|
||||
} catch {
|
||||
}
|
||||
}, Be = (e) => e ? new Set(e.map((t) => t.name)) : /* @__PURE__ */ new Set(), Ye = (e, t = "") => {
|
||||
if (!t) return !1;
|
||||
if (e.has(t) || [...e].some((n) => n.startsWith(t))) return !0;
|
||||
let r = t;
|
||||
for (; r.includes(":"); )
|
||||
if (r = r.slice(0, r.lastIndexOf(":")), e.has(`${r}:*`)) return !0;
|
||||
}, we = (e) => e ? new Set(e.map((r) => r.name)) : /* @__PURE__ */ new Set(), Ye = (e, r = "") => {
|
||||
if (!r) return !1;
|
||||
if (e.has(r) || [...e].some((n) => n.startsWith(r))) return !0;
|
||||
let t = r;
|
||||
for (; t.includes(":"); )
|
||||
if (t = t.slice(0, t.lastIndexOf(":")), e.has(`${t}:*`)) return !0;
|
||||
return !1;
|
||||
}, Q = {
|
||||
}, H = {
|
||||
all: ["permissions"],
|
||||
list: (e) => [...Q.all, e]
|
||||
}, Oe = async (e) => {
|
||||
list: (e) => [...H.all, e]
|
||||
}, fe = async (e) => {
|
||||
if (!(e != null && e.url) || !(e != null && e.clientId))
|
||||
throw new Error("Permission config requires url and clientId.");
|
||||
const t = w(), r = new URL(e.url);
|
||||
r.searchParams.set("client_id", e.clientId);
|
||||
const n = await fetch(r.toString(), {
|
||||
const r = x(), t = new URL(e.url);
|
||||
t.searchParams.set("client_id", e.clientId);
|
||||
const n = await fetch(t.toString(), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
...t ? { Authorization: `Bearer ${t}` } : {}
|
||||
...r ? { Authorization: `Bearer ${r}` } : {}
|
||||
}
|
||||
});
|
||||
if (!n.ok)
|
||||
throw new Error("Failed to load permissions");
|
||||
return n.json();
|
||||
}, A = () => {
|
||||
const e = ee(k);
|
||||
}, P = () => {
|
||||
const e = $(J);
|
||||
if (!e)
|
||||
throw new Error("usePermission must be used within PermissionProvider");
|
||||
return e;
|
||||
}, fe = (e) => f({
|
||||
queryKey: Q.list(e == null ? void 0 : e.clientId),
|
||||
queryFn: () => Oe(e),
|
||||
enabled: !!(e != null && e.url) && !!(e != null && e.clientId) && I(),
|
||||
}, We = (e) => f({
|
||||
queryKey: H.list(e == null ? void 0 : e.clientId),
|
||||
queryFn: () => fe(e),
|
||||
enabled: !!(e != null && e.url) && !!(e != null && e.clientId) && N(),
|
||||
staleTime: 1 / 0,
|
||||
refetchOnWindowFocus: !1,
|
||||
refetchOnReconnect: !1
|
||||
}), ke = ({
|
||||
}), Qe = ({
|
||||
perm: e,
|
||||
children: t,
|
||||
fallback: r = /* @__PURE__ */ q("div", { children: "You are not allowed to do this" })
|
||||
children: r,
|
||||
fallback: t = /* @__PURE__ */ Z("div", { children: "You are not allowed to do this" })
|
||||
}) => {
|
||||
const { can: n } = A();
|
||||
return n(e) ? t : r;
|
||||
}, Qe = ({ children: e }) => {
|
||||
const { can: t, permissions: r } = A();
|
||||
return r && t("admin") ? e : null;
|
||||
}, je = ({ children: e, forceNoAccess: t = !1 }) => {
|
||||
const { can: r, isLoading: n } = A();
|
||||
return g(() => {
|
||||
n || (t || !r("panel_access")) && G();
|
||||
}, [n, r, t]), e;
|
||||
const { can: n } = P();
|
||||
return n(e) ? r : t;
|
||||
}, je = ({ children: e }) => {
|
||||
const { can: r, permissions: t } = P();
|
||||
return t && r("admin") ? e : null;
|
||||
}, _e = ({ children: e, forceNoAccess: r = !1 }) => {
|
||||
const { can: t, isLoading: n } = P();
|
||||
return z(() => {
|
||||
n || (r || !t("panel_access")) && R();
|
||||
}, [n, t, r]), e;
|
||||
};
|
||||
function We() {
|
||||
const [e, t] = z(!1), r = N(null);
|
||||
return g(() => {
|
||||
function Oe() {
|
||||
const [e, r] = X(!1), t = L(null);
|
||||
return z(() => {
|
||||
if (process.env.NODE_ENV !== "production") return;
|
||||
let n;
|
||||
const u = async () => {
|
||||
const d = await fetch(`/version.json?t=${Date.now()}`, {
|
||||
const d = async () => {
|
||||
const u = await fetch(`/version.json?t=${Date.now()}`, {
|
||||
cache: "no-store"
|
||||
});
|
||||
if (!d.ok)
|
||||
throw new Error(`Failed to fetch version: ${d.status}`);
|
||||
const s = await d.json();
|
||||
if (!u.ok)
|
||||
throw new Error(`Failed to fetch version: ${u.status}`);
|
||||
const s = await u.json();
|
||||
return String(s.version);
|
||||
};
|
||||
return (async () => {
|
||||
try {
|
||||
r.current = await u(), n = setInterval(async () => {
|
||||
t.current = await d(), n = setInterval(async () => {
|
||||
try {
|
||||
const d = await u();
|
||||
r.current && d !== r.current && (t(!0), clearInterval(n));
|
||||
} catch (d) {
|
||||
console.error("Update check failed:", d);
|
||||
const u = await d();
|
||||
t.current && u !== t.current && (r(!0), clearInterval(n));
|
||||
} catch (u) {
|
||||
console.error("Update check failed:", u);
|
||||
}
|
||||
}, 3e4);
|
||||
} catch (d) {
|
||||
console.error("Initial version fetch failed:", d);
|
||||
} catch (u) {
|
||||
console.error("Initial version fetch failed:", u);
|
||||
}
|
||||
})(), () => {
|
||||
n && clearInterval(n);
|
||||
};
|
||||
}, []), e ? /* @__PURE__ */ q(
|
||||
}, []), e ? /* @__PURE__ */ Z(
|
||||
"div",
|
||||
{
|
||||
style: {
|
||||
@ -364,7 +365,7 @@ function We() {
|
||||
}
|
||||
) : null;
|
||||
}
|
||||
const ve = new ne({
|
||||
const ve = new re({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: 1,
|
||||
@ -395,7 +396,7 @@ const ve = new ne({
|
||||
}
|
||||
},
|
||||
se({ colorScheme: "facebook" })
|
||||
), Me = () => /* @__PURE__ */ q(
|
||||
), De = () => /* @__PURE__ */ Z(
|
||||
de,
|
||||
{
|
||||
styles: `
|
||||
@ -408,115 +409,111 @@ const ve = new ne({
|
||||
}
|
||||
`
|
||||
}
|
||||
), U = "__UIKIT_REMOTE_DEPS__", L = "__UIKIT_REMOTE_CONFIG__";
|
||||
function De({ theme: e, remoteUiUrl: t, chakraProviderProps: r } = {}) {
|
||||
), U = "__UIKIT_REMOTE_DEPS__";
|
||||
function Me({ theme: e, chakraProviderProps: r } = {}) {
|
||||
if (typeof window > "u") return;
|
||||
const n = window[U] || {}, u = window[L] || {};
|
||||
const t = window[U] || {};
|
||||
window[U] = {
|
||||
...n,
|
||||
React: n.React || $,
|
||||
ChakraProvider: n.ChakraProvider || R,
|
||||
Badge: n.Badge || ue,
|
||||
theme: e ?? n.theme,
|
||||
...t,
|
||||
React: t.React || _,
|
||||
createRoot: t.createRoot || oe,
|
||||
ChakraProvider: t.ChakraProvider || V,
|
||||
Badge: t.Badge || ue,
|
||||
theme: e ?? t.theme,
|
||||
chakraProviderProps: {
|
||||
...n.chakraProviderProps || {},
|
||||
...t.chakraProviderProps || {},
|
||||
...r || {}
|
||||
}
|
||||
}, window[L] = {
|
||||
...u,
|
||||
...t ? { GBadgeUrl: t } : {}
|
||||
};
|
||||
}
|
||||
function _e({
|
||||
function $e({
|
||||
children: e,
|
||||
apiBaseUrl: t,
|
||||
keycloakClientId: r,
|
||||
apiBaseUrl: r,
|
||||
keycloakClientId: t,
|
||||
permissionClientId: n,
|
||||
loading: u = /* @__PURE__ */ q(ae, {}),
|
||||
updateChecker: h = !1,
|
||||
updateCheckerProps: d,
|
||||
loading: d = /* @__PURE__ */ Z(ae, {}),
|
||||
updateChecker: l = !1,
|
||||
updateCheckerProps: u,
|
||||
keycloakUrl: s = "https://auth.ibagher.ir",
|
||||
keycloakRealm: a = "bi",
|
||||
permissionUrl: S = "https://api.d.aiengines.ir/user_api/v1/permissions/list",
|
||||
permissionUrl: F = "https://api.d.aiengines.ir/user_api/v1/permissions/list",
|
||||
keycloakEnabled: p,
|
||||
permissionEnabled: i,
|
||||
theme: l = Ae,
|
||||
theme: c = Ae,
|
||||
remoteUiEnabled: m = !0,
|
||||
remoteUiUrl: F,
|
||||
remoteUiChakraProviderProps: E
|
||||
remoteUiChakraProviderProps: S
|
||||
}) {
|
||||
const [c, Z] = z(!1), b = p ?? !!r, y = i ?? !!n, T = x(
|
||||
const [q, h] = X(!1), E = p ?? !!t, b = i ?? !!n, y = g(
|
||||
() => ({
|
||||
api: {
|
||||
baseUrl: t || ""
|
||||
baseUrl: r || ""
|
||||
},
|
||||
keycloak: b ? {
|
||||
keycloak: E ? {
|
||||
url: s,
|
||||
realm: a,
|
||||
clientId: r
|
||||
clientId: t
|
||||
} : null,
|
||||
permission: y ? {
|
||||
url: S,
|
||||
permission: b ? {
|
||||
url: F,
|
||||
clientId: n
|
||||
} : null
|
||||
}),
|
||||
[
|
||||
t,
|
||||
r,
|
||||
E,
|
||||
b,
|
||||
y,
|
||||
s,
|
||||
a,
|
||||
r,
|
||||
S,
|
||||
t,
|
||||
F,
|
||||
n
|
||||
]
|
||||
);
|
||||
if (g(() => {
|
||||
Z(!0);
|
||||
}, []), g(() => {
|
||||
c && me(T);
|
||||
}, [c, T]), !c)
|
||||
if (z(() => {
|
||||
h(!0);
|
||||
}, []), z(() => {
|
||||
q && me(y);
|
||||
}, [q, y]), !q)
|
||||
return null;
|
||||
m && De({
|
||||
theme: l,
|
||||
remoteUiUrl: F,
|
||||
chakraProviderProps: E
|
||||
m && Me({
|
||||
theme: c,
|
||||
chakraProviderProps: S
|
||||
});
|
||||
let K = e;
|
||||
return y && (K = /* @__PURE__ */ q(ge, { config: T.permission, loading: u, children: K })), b && (K = /* @__PURE__ */ q(Se, { config: T.keycloak, loading: u, children: K })), /* @__PURE__ */ M(R, { theme: l, children: [
|
||||
/* @__PURE__ */ q(Me, {}),
|
||||
/* @__PURE__ */ M(oe, { client: ve, children: [
|
||||
h && /* @__PURE__ */ q(We, { ...d }),
|
||||
K
|
||||
let T = e;
|
||||
return b && (T = /* @__PURE__ */ Z(xe, { config: y.permission, loading: d, children: T })), E && (T = /* @__PURE__ */ Z(Fe, { config: y.keycloak, loading: d, children: T })), /* @__PURE__ */ A(V, { theme: c, children: [
|
||||
/* @__PURE__ */ Z(De, {}),
|
||||
/* @__PURE__ */ A(ne, { client: ve, children: [
|
||||
l && /* @__PURE__ */ Z(Oe, { ...u }),
|
||||
T
|
||||
] })
|
||||
] });
|
||||
}
|
||||
export {
|
||||
Qe as AdminGuard,
|
||||
_e as BiProvider,
|
||||
ke as Can,
|
||||
Se as KeycloakProvider,
|
||||
je as PanelAccessGuard,
|
||||
ge as PermissionProvider,
|
||||
H as api,
|
||||
je as AdminGuard,
|
||||
$e as BiProvider,
|
||||
Qe as Can,
|
||||
Fe as KeycloakProvider,
|
||||
_e as PanelAccessGuard,
|
||||
xe as PermissionProvider,
|
||||
G as api,
|
||||
Ye as checkPermission,
|
||||
He as clearCachedPermissions,
|
||||
ke as clearCachedPermissions,
|
||||
me as configureApi,
|
||||
Je as createApi,
|
||||
Be as createPermissionSet,
|
||||
qe as fetcher,
|
||||
Ee as getApi,
|
||||
we as getCachedPermissions,
|
||||
w as getKeycloakToken,
|
||||
Oe as getPermissions,
|
||||
J as initKeycloak,
|
||||
I as isKeycloakAuthenticated,
|
||||
Fe as isKeycloakInitialized,
|
||||
Ge as loginKeycloak,
|
||||
G as logoutKeycloak,
|
||||
Q as permissionKeys,
|
||||
xe as setCachedPermissions,
|
||||
He as createApi,
|
||||
we as createPermissionSet,
|
||||
Ee as fetcher,
|
||||
qe as getApi,
|
||||
ge as getCachedPermissions,
|
||||
x as getKeycloakToken,
|
||||
fe as getPermissions,
|
||||
I as initKeycloak,
|
||||
N as isKeycloakAuthenticated,
|
||||
Se as isKeycloakInitialized,
|
||||
Je as loginKeycloak,
|
||||
R as logoutKeycloak,
|
||||
H as permissionKeys,
|
||||
Be as setCachedPermissions,
|
||||
D as updateKeycloakToken,
|
||||
A as usePermission,
|
||||
fe as usePermissionsQuery
|
||||
P as usePermission,
|
||||
We as usePermissionsQuery
|
||||
};
|
||||
|
||||
68
dist/remote-ui.d.ts
vendored
68
dist/remote-ui.d.ts
vendored
@ -1,54 +1,24 @@
|
||||
import type { BadgeProps, StackProps } from "@chakra-ui/react";
|
||||
import type { ReactNode } from "react";
|
||||
export {
|
||||
setupUikitRemoteDeps,
|
||||
} from "./_core/setupRemoteDeps";
|
||||
|
||||
export type UikitRemoteLevel = "full" | "compact" | "simple";
|
||||
export type {
|
||||
UikitRemoteSetupOptions,
|
||||
} from "./_core/setupRemoteDeps";
|
||||
|
||||
export interface UikitRemoteSetupOptions {
|
||||
React?: any;
|
||||
createRoot?: any;
|
||||
ChakraProvider?: any;
|
||||
Badge?: any;
|
||||
Button?: any;
|
||||
HStack?: any;
|
||||
IconButton?: any;
|
||||
Input?: any;
|
||||
Text?: any;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
export {
|
||||
GBadge,
|
||||
} from "./GBadge";
|
||||
|
||||
/** Backward compatible alias for GBadgeUrl. */
|
||||
remoteUrl?: string;
|
||||
GBadgeUrl?: string;
|
||||
PaginationUrl?: string;
|
||||
remoteUrls?: {
|
||||
GBadge?: string;
|
||||
Pagination?: string;
|
||||
};
|
||||
}
|
||||
export type {
|
||||
GBadgeProps,
|
||||
} from "./GBadge";
|
||||
|
||||
export declare function setupUikitRemoteDeps(
|
||||
options?: UikitRemoteSetupOptions,
|
||||
): void;
|
||||
export {
|
||||
Pagination,
|
||||
} from "./Pagination";
|
||||
|
||||
export interface GBadgeProps extends BadgeProps {
|
||||
children?: ReactNode;
|
||||
remoteUrl?: string;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare const GBadge: (props: GBadgeProps) => JSX.Element;
|
||||
|
||||
export interface PaginationProps extends Omit<StackProps, "onChange"> {
|
||||
currentPage?: number;
|
||||
totalCount?: number;
|
||||
totalPages?: number;
|
||||
pageSize?: number;
|
||||
onPageChange?: (page: number) => void;
|
||||
level?: UikitRemoteLevel;
|
||||
remoteUrl?: string;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare const Pagination: (props: PaginationProps) => JSX.Element;
|
||||
export type {
|
||||
PaginationLevel,
|
||||
PaginationProps,
|
||||
} from "./Pagination";
|
||||
|
||||
236
dist/remote-ui.js
vendored
236
dist/remote-ui.js
vendored
@ -1,13 +1,120 @@
|
||||
import { jsx as E } from "react/jsx-runtime";
|
||||
import p, { useRef as s, useEffect as R } from "react";
|
||||
import B, { useRef as d, useEffect as g } from "react";
|
||||
import { createRoot as k } from "react-dom/client";
|
||||
import { Text as U, Input as _, IconButton as I, HStack as v, Button as G, Badge as C, ChakraProvider as T } from "@chakra-ui/react";
|
||||
import { Text as v, Input as w, IconButton as E, HStack as y, Button as I, Badge as C, ChakraProvider as T } from "@chakra-ui/react";
|
||||
import { jsx as _ } from "react/jsx-runtime";
|
||||
const h = {
|
||||
GBadge: "https://uikit.d.aiengines.ir/GBadge.js",
|
||||
Pagination: "https://uikit.d.aiengines.ir/Pagination.js"
|
||||
}, l = "__UIKIT_REMOTE_DEPS__", g = "__UIKIT_REMOTE_CONFIG__", u = /* @__PURE__ */ new Map(), y = {
|
||||
GBadge: ["React", "createRoot", "ChakraProvider", "Badge"],
|
||||
Pagination: [
|
||||
}, s = "__UIKIT_REMOTE_DEPS__";
|
||||
function D(e = {}) {
|
||||
if (typeof window > "u") return;
|
||||
const t = window[s] || {};
|
||||
window[s] = {
|
||||
...t,
|
||||
React: e.React || t.React || B,
|
||||
createRoot: e.createRoot || t.createRoot || k,
|
||||
ChakraProvider: e.ChakraProvider || t.ChakraProvider || T,
|
||||
Badge: e.Badge || t.Badge || C,
|
||||
Button: e.Button || t.Button || I,
|
||||
HStack: e.HStack || t.HStack || y,
|
||||
IconButton: e.IconButton || t.IconButton || E,
|
||||
Input: e.Input || t.Input || w,
|
||||
Text: e.Text || t.Text || v,
|
||||
...e.deps || {},
|
||||
theme: Object.prototype.hasOwnProperty.call(e, "theme") ? e.theme : t.theme,
|
||||
chakraProviderProps: {
|
||||
...t.chakraProviderProps || {},
|
||||
...e.chakraProviderProps || {}
|
||||
}
|
||||
};
|
||||
}
|
||||
const a = /* @__PURE__ */ new Map();
|
||||
function x(e = []) {
|
||||
if (typeof window > "u") return !1;
|
||||
const t = window[s];
|
||||
return e.every((r) => t == null ? void 0 : t[r]);
|
||||
}
|
||||
function S(e = []) {
|
||||
typeof window > "u" || x(e) || D();
|
||||
}
|
||||
function G(e, t) {
|
||||
const r = `${e}:${t}`;
|
||||
return a.has(r) || a.set(
|
||||
r,
|
||||
import(
|
||||
/* webpackIgnore: true */
|
||||
/* @vite-ignore */
|
||||
t
|
||||
).catch((u) => {
|
||||
throw a.delete(r), u;
|
||||
})
|
||||
), a.get(r);
|
||||
}
|
||||
function P({
|
||||
componentName: e,
|
||||
tagName: t,
|
||||
defaultRemoteUrl: r,
|
||||
requiredDeps: u,
|
||||
normalizeProps: f
|
||||
}) {
|
||||
return function({
|
||||
theme: m,
|
||||
chakraProviderProps: l,
|
||||
...p
|
||||
}) {
|
||||
const i = d(null), n = d(null), c = d(null);
|
||||
return c.current = {
|
||||
...f ? f(p) : p,
|
||||
...m !== void 0 ? { theme: m } : {},
|
||||
...l ? { chakraProviderProps: l } : {}
|
||||
}, g(() => {
|
||||
let R = !0;
|
||||
return S(u), G(e, r).then(() => {
|
||||
if (!R || !i.current) return;
|
||||
const o = document.createElement(t);
|
||||
o.componentProps = c.current, i.current.appendChild(o), n.current = o;
|
||||
}).catch((o) => {
|
||||
console.error(
|
||||
`[uikit/remote/ui] Failed to load ${e}:`,
|
||||
o
|
||||
);
|
||||
}), () => {
|
||||
R = !1, n.current && (n.current.remove(), n.current = null);
|
||||
};
|
||||
}, [e, r, t]), g(() => {
|
||||
n.current && (n.current.componentProps = c.current);
|
||||
}), /* @__PURE__ */ _(
|
||||
"span",
|
||||
{
|
||||
ref: i,
|
||||
style: {
|
||||
display: "contents"
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
function b(e) {
|
||||
if (typeof e == "string" || typeof e == "number")
|
||||
return e;
|
||||
e != null && console.warn(
|
||||
"[uikit/remote/ui] GBadge only accepts text/number children across the remote boundary."
|
||||
);
|
||||
}
|
||||
const q = P({
|
||||
componentName: "GBadge",
|
||||
tagName: "uikit-g-badge",
|
||||
defaultRemoteUrl: h.GBadge,
|
||||
requiredDeps: ["React", "createRoot", "ChakraProvider", "Badge"],
|
||||
normalizeProps: ({ children: e, ...t }) => ({
|
||||
...t,
|
||||
children: b(e)
|
||||
})
|
||||
}), K = P({
|
||||
componentName: "Pagination",
|
||||
tagName: "uikit-pagination",
|
||||
defaultRemoteUrl: h.Pagination,
|
||||
requiredDeps: [
|
||||
"React",
|
||||
"createRoot",
|
||||
"ChakraProvider",
|
||||
@ -17,122 +124,9 @@ const h = {
|
||||
"Input",
|
||||
"Text"
|
||||
]
|
||||
};
|
||||
function D(e = {}) {
|
||||
if (typeof window > "u") return;
|
||||
const t = window[l] || {}, r = window[g] || {};
|
||||
window[l] = {
|
||||
...t,
|
||||
React: e.React || t.React || p,
|
||||
createRoot: e.createRoot || t.createRoot || k,
|
||||
ChakraProvider: e.ChakraProvider || t.ChakraProvider || T,
|
||||
Badge: e.Badge || t.Badge || C,
|
||||
Button: e.Button || t.Button || G,
|
||||
HStack: e.HStack || t.HStack || v,
|
||||
IconButton: e.IconButton || t.IconButton || I,
|
||||
Input: e.Input || t.Input || _,
|
||||
Text: e.Text || t.Text || U,
|
||||
theme: Object.prototype.hasOwnProperty.call(e, "theme") ? e.theme : t.theme,
|
||||
chakraProviderProps: {
|
||||
...t.chakraProviderProps || {},
|
||||
...e.chakraProviderProps || {}
|
||||
}
|
||||
};
|
||||
const n = e.remoteUrls || {};
|
||||
window[g] = {
|
||||
...r,
|
||||
...e.remoteUrl ? { GBadgeUrl: e.remoteUrl } : {},
|
||||
...e.GBadgeUrl ? { GBadgeUrl: e.GBadgeUrl } : {},
|
||||
...e.PaginationUrl ? { PaginationUrl: e.PaginationUrl } : {},
|
||||
...n.GBadge ? { GBadgeUrl: n.GBadge } : {},
|
||||
...n.Pagination ? { PaginationUrl: n.Pagination } : {}
|
||||
};
|
||||
}
|
||||
function O(e) {
|
||||
if (typeof window > "u") return;
|
||||
const t = window[l];
|
||||
(y[e] || []).some((o) => !(t != null && t[o])) && D();
|
||||
}
|
||||
function S(e, t) {
|
||||
var r;
|
||||
return t || (typeof window > "u" ? h[e] : ((r = window[g]) == null ? void 0 : r[`${e}Url`]) || h[e]);
|
||||
}
|
||||
function M(e, t) {
|
||||
const r = S(e, t), n = `${e}:${r}`;
|
||||
return u.has(n) || u.set(
|
||||
n,
|
||||
import(
|
||||
/* webpackIgnore: true */
|
||||
/* @vite-ignore */
|
||||
r
|
||||
).catch((o) => {
|
||||
throw u.delete(n), o;
|
||||
})
|
||||
), u.get(n);
|
||||
}
|
||||
function x(e) {
|
||||
if (typeof e == "string" || typeof e == "number")
|
||||
return e;
|
||||
e != null && console.warn(
|
||||
"[uikit/remote/ui] GBadge only accepts text/number children across the remote boundary."
|
||||
);
|
||||
}
|
||||
function w({
|
||||
componentName: e,
|
||||
tagName: t,
|
||||
normalizeProps: r
|
||||
}) {
|
||||
return function({
|
||||
remoteUrl: o,
|
||||
theme: f,
|
||||
chakraProviderProps: m,
|
||||
...B
|
||||
}) {
|
||||
const c = s(null), a = s(null), d = s(null);
|
||||
return d.current = {
|
||||
...r ? r(B) : B,
|
||||
...f !== void 0 ? { theme: f } : {},
|
||||
...m ? { chakraProviderProps: m } : {}
|
||||
}, R(() => {
|
||||
let P = !0;
|
||||
return O(e), M(e, o).then(() => {
|
||||
if (!P || !c.current) return;
|
||||
const i = document.createElement(t);
|
||||
i.componentProps = d.current, c.current.appendChild(i), a.current = i;
|
||||
}).catch((i) => {
|
||||
console.error(
|
||||
`[uikit/remote/ui] Failed to load ${e}:`,
|
||||
i
|
||||
);
|
||||
}), () => {
|
||||
P = !1, a.current && (a.current.remove(), a.current = null);
|
||||
};
|
||||
}, [e, o, t]), R(() => {
|
||||
a.current && (a.current.componentProps = d.current);
|
||||
}), /* @__PURE__ */ E(
|
||||
"span",
|
||||
{
|
||||
ref: c,
|
||||
style: {
|
||||
display: "contents"
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
const F = w({
|
||||
componentName: "GBadge",
|
||||
tagName: "uikit-g-badge",
|
||||
normalizeProps: ({ children: e, ...t }) => ({
|
||||
...t,
|
||||
children: x(e)
|
||||
})
|
||||
}), $ = w({
|
||||
componentName: "Pagination",
|
||||
tagName: "uikit-pagination"
|
||||
});
|
||||
export {
|
||||
F as GBadge,
|
||||
$ as Pagination,
|
||||
q as GBadge,
|
||||
K as Pagination,
|
||||
D as setupUikitRemoteDeps
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Badge, ChakraProvider, Spinner } from "@chakra-ui/react";
|
||||
import { QueryClientProvider } from "@tanstack/react-query";
|
||||
import { KeycloakProvider } from "./keycloak.jsx";
|
||||
@ -9,17 +10,14 @@ import { queryClient } from "./query.js";
|
||||
import { Fonts, theme as defaultTheme } from "./style.jsx";
|
||||
|
||||
const REMOTE_DEPS_KEY = "__UIKIT_REMOTE_DEPS__";
|
||||
const REMOTE_CONFIG_KEY = "__UIKIT_REMOTE_CONFIG__";
|
||||
|
||||
function setupBiRemoteUiDeps({ theme, remoteUiUrl, chakraProviderProps } = {}) {
|
||||
function setupBiRemoteUiDeps({ theme, chakraProviderProps } = {}) {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const previousDeps = window[REMOTE_DEPS_KEY] || {};
|
||||
const previousConfig = window[REMOTE_CONFIG_KEY] || {};
|
||||
|
||||
window[REMOTE_DEPS_KEY] = {
|
||||
...previousDeps,
|
||||
React: previousDeps.React || React,
|
||||
createRoot: previousDeps.createRoot || createRoot,
|
||||
ChakraProvider: previousDeps.ChakraProvider || ChakraProvider,
|
||||
Badge: previousDeps.Badge || Badge,
|
||||
theme: theme ?? previousDeps.theme,
|
||||
@ -28,11 +26,6 @@ function setupBiRemoteUiDeps({ theme, remoteUiUrl, chakraProviderProps } = {}) {
|
||||
...(chakraProviderProps || {}),
|
||||
},
|
||||
};
|
||||
|
||||
window[REMOTE_CONFIG_KEY] = {
|
||||
...previousConfig,
|
||||
...(remoteUiUrl ? { GBadgeUrl: remoteUiUrl } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function BiProvider({
|
||||
@ -57,7 +50,6 @@ export function BiProvider({
|
||||
|
||||
theme = defaultTheme,
|
||||
remoteUiEnabled = true,
|
||||
remoteUiUrl,
|
||||
remoteUiChakraProviderProps,
|
||||
}) {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
@ -115,7 +107,6 @@ export function BiProvider({
|
||||
if (remoteUiEnabled) {
|
||||
setupBiRemoteUiDeps({
|
||||
theme,
|
||||
remoteUiUrl,
|
||||
chakraProviderProps: remoteUiChakraProviderProps,
|
||||
});
|
||||
}
|
||||
|
||||
1
src/core/index.d.ts
vendored
1
src/core/index.d.ts
vendored
@ -41,7 +41,6 @@ export type BiProviderProps = {
|
||||
permissionEnabled?: boolean;
|
||||
theme?: any;
|
||||
remoteUiEnabled?: boolean;
|
||||
remoteUiUrl?: string;
|
||||
remoteUiChakraProviderProps?: Record<string, any>;
|
||||
};
|
||||
|
||||
|
||||
10
src/remote/ui/GBadge/index.d.ts
vendored
Normal file
10
src/remote/ui/GBadge/index.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import type { BadgeProps } from "@chakra-ui/react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export interface GBadgeProps extends BadgeProps {
|
||||
children?: ReactNode;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare const GBadge: (props: GBadgeProps) => JSX.Element;
|
||||
31
src/remote/ui/GBadge/index.jsx
Normal file
31
src/remote/ui/GBadge/index.jsx
Normal file
@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import { DEFAULT_REMOTE_URLS } from "../_core/constants";
|
||||
import { createRemoteElementComponent } from "../_core/createRemoteElementComponent";
|
||||
|
||||
function normalizeChildren(children) {
|
||||
if (typeof children === "string" || typeof children === "number") {
|
||||
return children;
|
||||
}
|
||||
|
||||
if (children === null || children === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"[uikit/remote/ui] GBadge only accepts text/number children across the remote boundary.",
|
||||
);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export const GBadge = createRemoteElementComponent({
|
||||
componentName: "GBadge",
|
||||
tagName: "uikit-g-badge",
|
||||
defaultRemoteUrl: DEFAULT_REMOTE_URLS.GBadge,
|
||||
requiredDeps: ["React", "createRoot", "ChakraProvider", "Badge"],
|
||||
normalizeProps: ({ children, ...props }) => ({
|
||||
...props,
|
||||
children: normalizeChildren(children),
|
||||
}),
|
||||
});
|
||||
16
src/remote/ui/Pagination/index.d.ts
vendored
Normal file
16
src/remote/ui/Pagination/index.d.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import type { StackProps } from "@chakra-ui/react";
|
||||
|
||||
export type PaginationLevel = "full" | "compact" | "simple";
|
||||
|
||||
export interface PaginationProps extends Omit<StackProps, "onChange"> {
|
||||
currentPage?: number;
|
||||
totalCount?: number;
|
||||
totalPages?: number;
|
||||
pageSize?: number;
|
||||
onPageChange?: (page: number) => void;
|
||||
level?: PaginationLevel;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare const Pagination: (props: PaginationProps) => JSX.Element;
|
||||
20
src/remote/ui/Pagination/index.jsx
Normal file
20
src/remote/ui/Pagination/index.jsx
Normal file
@ -0,0 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import { DEFAULT_REMOTE_URLS } from "../_core/constants";
|
||||
import { createRemoteElementComponent } from "../_core/createRemoteElementComponent";
|
||||
|
||||
export const Pagination = createRemoteElementComponent({
|
||||
componentName: "Pagination",
|
||||
tagName: "uikit-pagination",
|
||||
defaultRemoteUrl: DEFAULT_REMOTE_URLS.Pagination,
|
||||
requiredDeps: [
|
||||
"React",
|
||||
"createRoot",
|
||||
"ChakraProvider",
|
||||
"Button",
|
||||
"HStack",
|
||||
"IconButton",
|
||||
"Input",
|
||||
"Text",
|
||||
],
|
||||
});
|
||||
6
src/remote/ui/_core/constants.js
Normal file
6
src/remote/ui/_core/constants.js
Normal file
@ -0,0 +1,6 @@
|
||||
export const DEFAULT_REMOTE_URLS = {
|
||||
GBadge: "https://uikit.d.aiengines.ir/GBadge.js",
|
||||
Pagination: "https://uikit.d.aiengines.ir/Pagination.js",
|
||||
};
|
||||
|
||||
export const REMOTE_DEPS_KEY = "__UIKIT_REMOTE_DEPS__";
|
||||
117
src/remote/ui/_core/createRemoteElementComponent.jsx
Normal file
117
src/remote/ui/_core/createRemoteElementComponent.jsx
Normal file
@ -0,0 +1,117 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
import { REMOTE_DEPS_KEY } from "./constants";
|
||||
import { setupUikitRemoteDeps } from "./setupRemoteDeps";
|
||||
|
||||
const remotePromises = new Map();
|
||||
|
||||
function hasRequiredDeps(requiredDeps = []) {
|
||||
if (typeof window === "undefined") return false;
|
||||
|
||||
const deps = window[REMOTE_DEPS_KEY];
|
||||
|
||||
return requiredDeps.every((key) => deps?.[key]);
|
||||
}
|
||||
|
||||
function ensureRemoteDeps(requiredDeps = []) {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
if (!hasRequiredDeps(requiredDeps)) {
|
||||
setupUikitRemoteDeps();
|
||||
}
|
||||
}
|
||||
|
||||
function loadRemote(componentName, remoteFileUrl) {
|
||||
const cacheKey = `${componentName}:${remoteFileUrl}`;
|
||||
|
||||
if (!remotePromises.has(cacheKey)) {
|
||||
remotePromises.set(
|
||||
cacheKey,
|
||||
import(
|
||||
/* webpackIgnore: true */
|
||||
/* @vite-ignore */
|
||||
remoteFileUrl
|
||||
).catch((error) => {
|
||||
remotePromises.delete(cacheKey);
|
||||
throw error;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return remotePromises.get(cacheKey);
|
||||
}
|
||||
|
||||
export function createRemoteElementComponent({
|
||||
componentName,
|
||||
tagName,
|
||||
defaultRemoteUrl,
|
||||
requiredDeps,
|
||||
normalizeProps,
|
||||
}) {
|
||||
return function RemoteElementComponent({
|
||||
theme,
|
||||
chakraProviderProps,
|
||||
...props
|
||||
}) {
|
||||
const containerRef = useRef(null);
|
||||
const elementRef = useRef(null);
|
||||
const latestPropsRef = useRef(null);
|
||||
|
||||
latestPropsRef.current = {
|
||||
...(normalizeProps ? normalizeProps(props) : props),
|
||||
...(theme !== undefined ? { theme } : {}),
|
||||
...(chakraProviderProps ? { chakraProviderProps } : {}),
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
|
||||
ensureRemoteDeps(requiredDeps);
|
||||
|
||||
loadRemote(componentName, defaultRemoteUrl)
|
||||
.then(() => {
|
||||
if (!active) return;
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const element = document.createElement(tagName);
|
||||
|
||||
element.componentProps = latestPropsRef.current;
|
||||
|
||||
containerRef.current.appendChild(element);
|
||||
elementRef.current = element;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
`[uikit/remote/ui] Failed to load ${componentName}:`,
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
|
||||
if (elementRef.current) {
|
||||
elementRef.current.remove();
|
||||
elementRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [componentName, defaultRemoteUrl, tagName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!elementRef.current) return;
|
||||
|
||||
elementRef.current.componentProps = latestPropsRef.current;
|
||||
});
|
||||
|
||||
return (
|
||||
<span
|
||||
ref={containerRef}
|
||||
style={{
|
||||
display: "contents",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
22
src/remote/ui/_core/setupRemoteDeps.d.ts
vendored
Normal file
22
src/remote/ui/_core/setupRemoteDeps.d.ts
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
export interface UikitRemoteSetupOptions {
|
||||
React?: any;
|
||||
createRoot?: any;
|
||||
|
||||
ChakraProvider?: any;
|
||||
|
||||
Badge?: any;
|
||||
Button?: any;
|
||||
HStack?: any;
|
||||
IconButton?: any;
|
||||
Input?: any;
|
||||
Text?: any;
|
||||
|
||||
deps?: Record<string, any>;
|
||||
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare function setupUikitRemoteDeps(
|
||||
options?: UikitRemoteSetupOptions,
|
||||
): void;
|
||||
49
src/remote/ui/_core/setupRemoteDeps.js
Normal file
49
src/remote/ui/_core/setupRemoteDeps.js
Normal file
@ -0,0 +1,49 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
ChakraProvider,
|
||||
HStack,
|
||||
IconButton,
|
||||
Input,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
|
||||
import { REMOTE_DEPS_KEY } from "./constants";
|
||||
|
||||
export function setupUikitRemoteDeps(options = {}) {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const previousDeps = window[REMOTE_DEPS_KEY] || {};
|
||||
|
||||
window[REMOTE_DEPS_KEY] = {
|
||||
...previousDeps,
|
||||
|
||||
React: options.React || previousDeps.React || React,
|
||||
createRoot: options.createRoot || previousDeps.createRoot || createRoot,
|
||||
|
||||
ChakraProvider:
|
||||
options.ChakraProvider || previousDeps.ChakraProvider || ChakraProvider,
|
||||
|
||||
Badge: options.Badge || previousDeps.Badge || Badge,
|
||||
Button: options.Button || previousDeps.Button || Button,
|
||||
HStack: options.HStack || previousDeps.HStack || HStack,
|
||||
IconButton: options.IconButton || previousDeps.IconButton || IconButton,
|
||||
Input: options.Input || previousDeps.Input || Input,
|
||||
Text: options.Text || previousDeps.Text || Text,
|
||||
|
||||
...(options.deps || {}),
|
||||
|
||||
theme: Object.prototype.hasOwnProperty.call(options, "theme")
|
||||
? options.theme
|
||||
: previousDeps.theme,
|
||||
|
||||
chakraProviderProps: {
|
||||
...(previousDeps.chakraProviderProps || {}),
|
||||
...(options.chakraProviderProps || {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
68
src/remote/ui/index.d.ts
vendored
68
src/remote/ui/index.d.ts
vendored
@ -1,54 +1,24 @@
|
||||
import type { BadgeProps, StackProps } from "@chakra-ui/react";
|
||||
import type { ReactNode } from "react";
|
||||
export {
|
||||
setupUikitRemoteDeps,
|
||||
} from "./_core/setupRemoteDeps";
|
||||
|
||||
export type UikitRemoteLevel = "full" | "compact" | "simple";
|
||||
export type {
|
||||
UikitRemoteSetupOptions,
|
||||
} from "./_core/setupRemoteDeps";
|
||||
|
||||
export interface UikitRemoteSetupOptions {
|
||||
React?: any;
|
||||
createRoot?: any;
|
||||
ChakraProvider?: any;
|
||||
Badge?: any;
|
||||
Button?: any;
|
||||
HStack?: any;
|
||||
IconButton?: any;
|
||||
Input?: any;
|
||||
Text?: any;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
export {
|
||||
GBadge,
|
||||
} from "./GBadge";
|
||||
|
||||
/** Backward compatible alias for GBadgeUrl. */
|
||||
remoteUrl?: string;
|
||||
GBadgeUrl?: string;
|
||||
PaginationUrl?: string;
|
||||
remoteUrls?: {
|
||||
GBadge?: string;
|
||||
Pagination?: string;
|
||||
};
|
||||
}
|
||||
export type {
|
||||
GBadgeProps,
|
||||
} from "./GBadge";
|
||||
|
||||
export declare function setupUikitRemoteDeps(
|
||||
options?: UikitRemoteSetupOptions,
|
||||
): void;
|
||||
export {
|
||||
Pagination,
|
||||
} from "./Pagination";
|
||||
|
||||
export interface GBadgeProps extends BadgeProps {
|
||||
children?: ReactNode;
|
||||
remoteUrl?: string;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare const GBadge: (props: GBadgeProps) => JSX.Element;
|
||||
|
||||
export interface PaginationProps extends Omit<StackProps, "onChange"> {
|
||||
currentPage?: number;
|
||||
totalCount?: number;
|
||||
totalPages?: number;
|
||||
pageSize?: number;
|
||||
onPageChange?: (page: number) => void;
|
||||
level?: UikitRemoteLevel;
|
||||
remoteUrl?: string;
|
||||
theme?: any;
|
||||
chakraProviderProps?: Record<string, any>;
|
||||
}
|
||||
|
||||
export declare const Pagination: (props: PaginationProps) => JSX.Element;
|
||||
export type {
|
||||
PaginationLevel,
|
||||
PaginationProps,
|
||||
} from "./Pagination";
|
||||
|
||||
@ -1,225 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
ChakraProvider,
|
||||
HStack,
|
||||
IconButton,
|
||||
Input,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
export { setupUikitRemoteDeps } from "./_core/setupRemoteDeps";
|
||||
|
||||
const DEFAULT_REMOTE_URLS = {
|
||||
GBadge: "https://uikit.d.aiengines.ir/GBadge.js",
|
||||
Pagination: "https://uikit.d.aiengines.ir/Pagination.js",
|
||||
};
|
||||
|
||||
const REMOTE_DEPS_KEY = "__UIKIT_REMOTE_DEPS__";
|
||||
const REMOTE_CONFIG_KEY = "__UIKIT_REMOTE_CONFIG__";
|
||||
|
||||
const remotePromises = new Map();
|
||||
|
||||
const REQUIRED_DEPS = {
|
||||
GBadge: ["React", "createRoot", "ChakraProvider", "Badge"],
|
||||
Pagination: [
|
||||
"React",
|
||||
"createRoot",
|
||||
"ChakraProvider",
|
||||
"Button",
|
||||
"HStack",
|
||||
"IconButton",
|
||||
"Input",
|
||||
"Text",
|
||||
],
|
||||
};
|
||||
|
||||
export function setupUikitRemoteDeps(options = {}) {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const previousDeps = window[REMOTE_DEPS_KEY] || {};
|
||||
const previousConfig = window[REMOTE_CONFIG_KEY] || {};
|
||||
|
||||
window[REMOTE_DEPS_KEY] = {
|
||||
...previousDeps,
|
||||
React: options.React || previousDeps.React || React,
|
||||
createRoot: options.createRoot || previousDeps.createRoot || createRoot,
|
||||
ChakraProvider:
|
||||
options.ChakraProvider || previousDeps.ChakraProvider || ChakraProvider,
|
||||
Badge: options.Badge || previousDeps.Badge || Badge,
|
||||
Button: options.Button || previousDeps.Button || Button,
|
||||
HStack: options.HStack || previousDeps.HStack || HStack,
|
||||
IconButton: options.IconButton || previousDeps.IconButton || IconButton,
|
||||
Input: options.Input || previousDeps.Input || Input,
|
||||
Text: options.Text || previousDeps.Text || Text,
|
||||
theme: Object.prototype.hasOwnProperty.call(options, "theme")
|
||||
? options.theme
|
||||
: previousDeps.theme,
|
||||
chakraProviderProps: {
|
||||
...(previousDeps.chakraProviderProps || {}),
|
||||
...(options.chakraProviderProps || {}),
|
||||
},
|
||||
};
|
||||
|
||||
const remoteUrls = options.remoteUrls || {};
|
||||
|
||||
window[REMOTE_CONFIG_KEY] = {
|
||||
...previousConfig,
|
||||
...(options.remoteUrl ? { GBadgeUrl: options.remoteUrl } : {}),
|
||||
...(options.GBadgeUrl ? { GBadgeUrl: options.GBadgeUrl } : {}),
|
||||
...(options.PaginationUrl ? { PaginationUrl: options.PaginationUrl } : {}),
|
||||
...(remoteUrls.GBadge ? { GBadgeUrl: remoteUrls.GBadge } : {}),
|
||||
...(remoteUrls.Pagination ? { PaginationUrl: remoteUrls.Pagination } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function ensureRemoteDeps(componentName) {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const deps = window[REMOTE_DEPS_KEY];
|
||||
const requiredDeps = REQUIRED_DEPS[componentName] || [];
|
||||
const hasMissingDeps = requiredDeps.some((key) => !deps?.[key]);
|
||||
|
||||
if (hasMissingDeps) {
|
||||
setupUikitRemoteDeps();
|
||||
}
|
||||
}
|
||||
|
||||
function getRemoteUrl(componentName, explicitRemoteUrl) {
|
||||
if (explicitRemoteUrl) return explicitRemoteUrl;
|
||||
|
||||
if (typeof window === "undefined") {
|
||||
return DEFAULT_REMOTE_URLS[componentName];
|
||||
}
|
||||
|
||||
return (
|
||||
window[REMOTE_CONFIG_KEY]?.[`${componentName}Url`] ||
|
||||
DEFAULT_REMOTE_URLS[componentName]
|
||||
);
|
||||
}
|
||||
|
||||
function loadRemote(componentName, explicitRemoteUrl) {
|
||||
const remoteUrl = getRemoteUrl(componentName, explicitRemoteUrl);
|
||||
const cacheKey = `${componentName}:${remoteUrl}`;
|
||||
|
||||
if (!remotePromises.has(cacheKey)) {
|
||||
remotePromises.set(
|
||||
cacheKey,
|
||||
import(
|
||||
/* webpackIgnore: true */
|
||||
/* @vite-ignore */
|
||||
remoteUrl
|
||||
).catch((error) => {
|
||||
remotePromises.delete(cacheKey);
|
||||
throw error;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return remotePromises.get(cacheKey);
|
||||
}
|
||||
|
||||
function normalizeBadgeChildren(children) {
|
||||
if (typeof children === "string" || typeof children === "number") {
|
||||
return children;
|
||||
}
|
||||
|
||||
if (children === null || children === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"[uikit/remote/ui] GBadge only accepts text/number children across the remote boundary.",
|
||||
);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function createRemoteElementComponent({
|
||||
componentName,
|
||||
tagName,
|
||||
normalizeProps,
|
||||
}) {
|
||||
return function RemoteElementComponent({
|
||||
remoteUrl,
|
||||
theme,
|
||||
chakraProviderProps,
|
||||
...props
|
||||
}) {
|
||||
const containerRef = useRef(null);
|
||||
const elementRef = useRef(null);
|
||||
const latestPropsRef = useRef(null);
|
||||
|
||||
latestPropsRef.current = {
|
||||
...(normalizeProps ? normalizeProps(props) : props),
|
||||
...(theme !== undefined ? { theme } : {}),
|
||||
...(chakraProviderProps ? { chakraProviderProps } : {}),
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
|
||||
ensureRemoteDeps(componentName);
|
||||
|
||||
loadRemote(componentName, remoteUrl)
|
||||
.then(() => {
|
||||
if (!active) return;
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const element = document.createElement(tagName);
|
||||
|
||||
element.componentProps = latestPropsRef.current;
|
||||
|
||||
containerRef.current.appendChild(element);
|
||||
|
||||
elementRef.current = element;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
`[uikit/remote/ui] Failed to load ${componentName}:`,
|
||||
error,
|
||||
);
|
||||
});
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
|
||||
if (elementRef.current) {
|
||||
elementRef.current.remove();
|
||||
elementRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [componentName, remoteUrl, tagName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!elementRef.current) return;
|
||||
|
||||
elementRef.current.componentProps = latestPropsRef.current;
|
||||
});
|
||||
|
||||
return (
|
||||
<span
|
||||
ref={containerRef}
|
||||
style={{
|
||||
display: "contents",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const GBadge = createRemoteElementComponent({
|
||||
componentName: "GBadge",
|
||||
tagName: "uikit-g-badge",
|
||||
normalizeProps: ({ children, ...props }) => ({
|
||||
...props,
|
||||
children: normalizeBadgeChildren(children),
|
||||
}),
|
||||
});
|
||||
|
||||
export const Pagination = createRemoteElementComponent({
|
||||
componentName: "Pagination",
|
||||
tagName: "uikit-pagination",
|
||||
});
|
||||
export { GBadge } from "./GBadge";
|
||||
export { Pagination } from "./Pagination";
|
||||
|
||||
@ -51,11 +51,11 @@ export default defineConfig(({ mode }) => {
|
||||
entry: {
|
||||
GBadge: path.resolve(
|
||||
process.cwd(),
|
||||
"src/remote/ui/GBadge.remote.jsx",
|
||||
"src/remote/ui/GBadge/GBadge.remote.jsx",
|
||||
),
|
||||
Pagination: path.resolve(
|
||||
process.cwd(),
|
||||
"src/remote/ui/Pagination.remote.jsx",
|
||||
"src/remote/ui/Pagination/Pagination.remote.jsx",
|
||||
),
|
||||
},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user