important changes
All checks were successful
Build and Deploy Next.js + Nginx Docker Image / build-and-deploy (push) Successful in 50s
Build and Deploy Next.js + Nginx Docker Image / deploy (push) Successful in 7s

This commit is contained in:
Mohamadzadeh 2026-07-14 16:33:32 +03:30
parent e1f501fa48
commit c75420a91c
19 changed files with 692 additions and 720 deletions

1
dist/core.d.ts vendored
View File

@ -41,7 +41,6 @@ export type BiProviderProps = {
permissionEnabled?: boolean;
theme?: any;
remoteUiEnabled?: boolean;
remoteUiUrl?: string;
remoteUiChakraProviderProps?: Record<string, any>;
};

523
dist/core.js vendored
View File

@ -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
View File

@ -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
View File

@ -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
};

View File

@ -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
View File

@ -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
View 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;

View 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
View 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;

View 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",
],
});

View 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__";

View 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",
}}
/>
);
};
}

View 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;

View 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 || {}),
},
};
}

View File

@ -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";

View File

@ -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";

View File

@ -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",
),
},